<mutex>和<condition_variable>的异常处理

jot*_*tik 11 c++ multithreading mutex condition-variable c++11

假设

  1. 没有未定义的行为,
  2. 没有死锁发生,
  3. 正确的线程以正确的顺序锁定和解锁互斥锁正确的次数,
  4. 非递归互斥锁未被多次锁定,
  5. 锁定递归互斥锁不超过最大所有权级别,
  6. 没有谓词传递给条件变量throw,和
  7. 只有标准库提供的时钟,时间点和持续时间与std::互斥锁和条件变量一起使用

是否保证对不同类型的std::互斥锁和条件变量(除了构造它们)的操作不会抛出任何异常(特别是类型std::system_error)?

例如,在以下方法的情况下:

void MyClass::setVariable() {
    std::lock_guard<std::mutex> const guard(m_mutex);
    m_var = 42; // m_var is of type int
    m_conditionVariable.notify_all();
}

void MyClass::waitVariable() {
    std::unique_lock<std::mutex> lock(m_mutex);
    m_conditionVariable.wait(lock, [this]() noexcept { return m_var == 42; });
}
Run Code Online (Sandbox Code Playgroud)

是否可以安全地假设noexcept或者应该在呼叫者周围写一些try-catch块?或者有任何警告吗?

请考虑C++ 11,C++ 14及更高版本中所有类型的互斥锁和条件变量.

Ric*_*ges 9

简答:不(对不起)

std::system_error如果底层同步对象无法执行其操作,则将抛出任何这些操作.

这是因为同步原语的正确操作取决于:

  1. 可用的系统资源.

  2. 程序的其他一些部分不会使原语无效

虽然公平地说,如果(1)正在发生,可能是时候重新设计应用程序或在负载较少的机器上运行它.

如果(2)发生,程序在逻辑上不一致.

话虽如此,

或者应该在callites周围写一些try-catch块?

也没有.

您应该在以下条件下编写try/catch块:

  1. 程序能够对错误情况做一些有用的事情(例如修复它或询问用户是否要再次尝试)

  2. 您希望向错误添加一些信息并重新抛出它以提供诊断性痕迹痕迹(例如,嵌套异常)

  3. 您希望记录故障并继续.

否则,c ++异常处理的重点是允许RAII处理资源重新获取并允许异常流出调用堆栈,直到找到想要处理它的处理程序.

创建面包屑跟踪的示例:

void wait_for_object()
try
{
    _x.wait();  // let's say it throws a system_error on a loaded system
}
catch(...)
{
  std::throw_with_nested(std::runtime_error(__func__));
}
Run Code Online (Sandbox Code Playgroud)


ixS*_*Sci 2

感谢 TC现在提供的链接,我想说是的 \xe2\x80\x94 你的代码应该是安全的。由于将来标准device_or_resource_busy将被删除,并且正如该问题的作者所说,这种情况不可能以任何合理的方式发生,因此只有两种可能lock抛出:

\n\n
\n

(13.1) \xe2\x80\x94 操作不被允许 \xe2\x80\x94 如果线程没有\n 执行该操作的权限。

\n\n

(13.2) \xe2\x80\x94 resources_deadlock_would_occurr \xe2\x80\x94 如果实现检测到将发生死锁。

\n
\n\n

而这两种情况都被你的前提条件排除了。所以你的代码应该可以安全地使用 noexcept。

\n