为什么没有lock()在死锁的情况下抛出异常

时间:2016-09-06 18:40:33

标签: c++ multithreading c++11 c++14

假设我们有以下代码:

#include <mutex>
#include <thread>

std::mutex m;

void foo()
{
    m.lock();
}

int main()
{
    std::thread th(foo);
    m.lock();
    th.join();
}

我知道这段代码包含死锁,但我想知道C ++标准中的以下语句:

30.4.1.2互斥体类型[thread.mutex.requirements.mutex]

  

6表达式m.lock()应格式良好并具有以下内容   语义:

     

[...]

     

12抛出:需要例外时的system_error(30.2.2)。

     

13错误条件:

     

- (13.1)operation_not_permitted - 如果线程没有   特权执行操作。

     

- (13.2)resource_deadlock_would_occur - 如果实现检测到   会发生僵局。

     

- (13.3)device_or_resource_busy - 如果互斥锁已被锁定   阻止是不可能的。

正如我们所看到的,违反其中一条规则应该会导致异常:

30.2.2异常[thread.req.exception]

  

1本条款中描述的某些功能被指定为抛出   system_error类型的异常(19.5.7)。   如果检测到任何功能的错误情况或对操作系统或其他人的调用,则应抛出此类异常   底层API导致阻止库函数的错误   从满足其规格

我提供的代码肯定包含死锁。在这种情况下,标准库是否应抛出异常(因为g ++和Visual C ++不这样做)?如果没有,为什么?因为从我的观点来看,它似乎属于13.2(resource_deadlock_would_occur)或13.3(device_or_resource_busy)类别。

2 个答案:

答案 0 :(得分:5)

您应该编写代码来处理死锁异常,但不要依赖它们来解决死锁。无法保证会抛出死锁异常,因为无法保证检测到它们。换句话说,实现不必检测死锁,它只是可以,并且如果找到它们就是如何处理它们的。这并不意味着他们会被发现。

死锁代码是一个逻辑错误,不要编写可以死锁的代码。

答案 1 :(得分:0)

30.4.1.2.1 [thread.mutex.class]

  
      
  1. [注意:如果拥有互斥对象的线程在该对象上调用lock(),程序可能会死锁。如果实现可以检测到死锁,则可以观察到resource_deadlock_would_occur错误情况。 - 尾注]
  2.   

根据pthread_mutex_lock的pthread手册:

  

如果互斥锁类型为PTHREAD_MUTEX_NORMAL,则不提供死锁检测。尝试重新锁定互斥锁会导致死锁。如果某个线程尝试解锁未锁定的互斥锁或解锁的互斥锁,则会导致未定义的行为。

请记住,在引用的标准部分中:

  

- resource_deadlock_would_occur - 如果实现检测到会发生死锁。

关键字是 if