为什么 libc++ 允许 std::mutex 的递归锁定?
Why does libc++ allow recursive locking of std::mutex?
std::mutex
是非递归的,违反它是 UB。所以理论上一切皆有可能(包括作为 std::recursive_mutex
)),但是 libc++ seems to work fine ,这个程序输出
bye
#include <iostream>
#include <mutex>
std::mutex m;
int main() {
std::scoped_lock l1(m);
std::scoped_lock l2(m);
std::cout << "bye" << std::endl;
}
这是 libc++ 中的故意设计决定还是只是一些意外(例如,他们可以对互斥和 recursive_mutex 使用相同的逻辑)?
libstdc++ 挂起。
注意:我知道人们不应该依赖 UB,所以这与最佳实践无关,我只是对模糊的实现细节感到好奇。
这似乎不是有意设计的决定。 std::mutex
的 libc++ 实现只是平台的 POSIX 默认互斥锁的包装器。由于如果递归锁定也被定义为具有 UB,它们只是继承了平台的默认 POSIX 互斥体也恰好允许递归锁定的事实。
我得到相反的结果:libc++ 挂起而 libstdc++ 没有挂起
原因是如果文件未使用 -pthread
编译,线程支持将被禁用并且 std::mutex::lock
/unlock
成为 noops。添加 -pthread
使它们都如预期的那样死锁。
libc++ 默认使用线程支持构建,不需要 -pthread
标志,因此它 std::mutex::lock
实际上会获取锁,从而造成死锁。
std::mutex
是非递归的,违反它是 UB。所以理论上一切皆有可能(包括作为 std::recursive_mutex
)),但是 libc++ seems to work fine ,这个程序输出
bye
#include <iostream>
#include <mutex>
std::mutex m;
int main() {
std::scoped_lock l1(m);
std::scoped_lock l2(m);
std::cout << "bye" << std::endl;
}
这是 libc++ 中的故意设计决定还是只是一些意外(例如,他们可以对互斥和 recursive_mutex 使用相同的逻辑)?
libstdc++ 挂起。
注意:我知道人们不应该依赖 UB,所以这与最佳实践无关,我只是对模糊的实现细节感到好奇。
这似乎不是有意设计的决定。 std::mutex
的 libc++ 实现只是平台的 POSIX 默认互斥锁的包装器。由于如果递归锁定也被定义为具有 UB,它们只是继承了平台的默认 POSIX 互斥体也恰好允许递归锁定的事实。
我得到相反的结果:libc++ 挂起而 libstdc++ 没有挂起
原因是如果文件未使用 -pthread
编译,线程支持将被禁用并且 std::mutex::lock
/unlock
成为 noops。添加 -pthread
使它们都如预期的那样死锁。
libc++ 默认使用线程支持构建,不需要 -pthread
标志,因此它 std::mutex::lock
实际上会获取锁,从而造成死锁。