【问题标题】:Why does libc++ allow recursive locking of std::mutex?为什么 libc++ 允许递归锁定 std::mutex?
【发布时间】:2021-04-17 08:25:32
【问题描述】:

std::mutex 是非递归的,违反它的是 UB。所以理论上一切皆有可能(包括std::recursive_mutex)),但是libc++ seems to work fine,这个程序输出

再见

#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++ 中的有意设计决定还是只是一些意外(例如,他们可以对 mutex 和 recursive_mutex 使用相同的逻辑)?

libstdc++ 挂起。

注意:我知道人们不应该依赖 UB,所以这不是关于最佳实践,我只是对晦涩的实现细节感到好奇。

【问题讨论】:

  • 请考虑您选择的措辞以及“递归”的替代“嵌套”。例如,使用两个不同的互斥锁似乎更好地描述为嵌套,而重复锁定相同的互斥锁可能是“递归的”。还要考虑显示解锁它们的(替代)代码,可能相关的顺序,或者它没有完成。它是否会改变观察到的行为。
  • “似乎工作正常”是 UB 可以做到的。但是,您真正的意思是“在我的机器上使用特定版本的编译器和一组选项似乎可以正常工作”
  • @MarshallClow 我知道,我只是对“工作正常”的原因感到好奇......实际上是我没有在 Godbolt 中使用 -pthread ......愚蠢的错误,但 TIL 的东西......

标签: c++ libc++ stdmutex


【解决方案1】:

这似乎不是一个有意的设计决定。 std::mutex 的 libc++ 实现只是平台的 POSIX 默认互斥锁的包装。由于它也被定义为递归锁定时具有 UB,因此它们只是继承了平台的默认 POSIX 互斥体也恰好允许递归锁定的事实。

【讨论】:

    【解决方案2】:

    我得到相反的结果:libc++ 挂起而 libstdc++ 没有

    原因是如果文件不是用-pthread编译的,线程支持被禁用,std::mutex::lock/unlock变成noops。添加-pthread 会使它们都像预期的那样死锁。

    libc++ 在默认情况下是使用线程支持构建的,并且不需要-pthread 标志,因此它std::mutex::lock 确实获得了锁,从而产生了死锁。

    【讨论】:

    • 正确,我刚刚用 -pthread 尝试了我的 Godbolt
    • 但对我来说现在都挂了godbolt.org/z/ozT45G
    猜你喜欢
    • 2021-10-30
    • 2021-06-04
    • 1970-01-01
    • 1970-01-01
    • 2017-03-28
    • 2010-12-31
    • 1970-01-01
    • 2016-09-07
    • 1970-01-01
    相关资源
    最近更新 更多