为什么锁定 std::mutex 不会阻塞线程

Why locking a std::mutex doesn't block the thread

本文关键字:线程 mutex 锁定 std 为什么      更新时间:2023-10-16

我写了下面的代码来测试我对std::mutex

的理解
int main() {
    mutex m;
    m.lock();
    m.lock(); // expect to block the thread
}

然后是system_error: device or resource busy。第二个m.lock()不是应该阻止线程吗?

From std::mutex:

在调用lock或try_lock之前,调用线程不能拥有互斥锁。

and from std::mutex::lock:

如果锁被一个已经拥有互斥锁的线程调用,程序可能会死锁。或者,如果实现可以检测到死锁,则可能会观察到resource_deadlock_would_occurs错误条件。

异常子句:

在发生错误时抛出std::system_error,包括来自底层操作系统的可能阻止锁满足其规范的错误。在抛出任何异常的情况下,互斥锁不会被锁定。

因此它不应该阻塞线程。在您的平台上,该实现似乎能够检测到线程何时已经是锁的所有者并引发异常。如描述所示,这在其他平台上可能不会发生。

是不是第二个m.lock()应该阻塞线程?

不,它给出了未定义的行为。第二个m.lock()打破了这个要求:

c++ 11 30.4.1.2/7 require:如果m的类型为std::mutexstd::timed_mutex,则调用线程不拥有该互斥锁。

看起来你的实现能够检测到调用线程拥有互斥锁并给出一个错误;其他可能会无限期阻塞,或以其他方式失败。

(当我写这个答案时,问题中没有提到std::mutex)

这取决于你使用的互斥锁库和互斥锁类型——你还没有告诉我们。有些系统提供了一个"递归互斥锁",只有当它发生在同一个线程时才允许这样多次调用(那么在另一个线程可以锁定它之前,你必须有匹配数量的解锁),其他库认为这是一个错误,可能会优雅地失败(就像你的库一样)或有未定义的行为。