gpt4 book ai didi

c++ - 带有重复参数的 Scoped_lock

转载 作者:行者123 更新时间:2023-12-04 11:39:38 29 4
gpt4 key购买 nike

我使用 std::scoped_lock 来保护多线程环境中的对象对。但我发现 scoped_lock 如果两个参数相同,会导致死锁(在 Visual Studio 和 gcc 中)。例如,

#include <mutex>

struct S
{
mutable std::mutex m;
int v = 0;
S & operator = ( const S & b )
{
std::scoped_lock l( m, b.m );
v = b.v;
return * this;
}
};

int main()
{
S a;
a = a; //deadlock here!
}
我看到标准要求“如果 MutexTypes 之一不是递归互斥体,并且当前线程已经拥有......中的相应参数,则行为未定义”,请参阅
https://en.cppreference.com/w/cpp/thread/scoped_lock/scoped_lock
但是在我的示例中,在形式上,互斥锁在 scoped_locked 之前没有锁定。那么这是预期的程序行为吗?

最佳答案

你真正害怕的现象是“自我死锁”。它发生在同时满足 2 个条件时:

  • 线程调用 重复 mutex.lock() 在同一个互斥对象上,
  • 并且那个互斥体属于非递归类型,不支持这种递归锁定。

  • 在 C++ 中,您有 2 种类型的互斥锁:
  • std::mutex 是非递归类型 - 它更快并且需要更少的资源,
  • std::recursive_mutex 是递归类型 - 它更安全但需要更多资源。

  • 现在让我们将这些知识应用到您的具体示例中:
  • 在您的情况下,避免“ 自我死锁 ”的明显方法是避免“ 自我分配 ”。为此,只需添加额外的检查:
     S & operator = ( const S & b ) 
    {
    if (this != &b) // check it is not self assignment
    {
    std::scoped_lock l( m, b.m );
    v = b.v;
    }
    return * this;
    }
  • 如果这是您 的唯一用法互斥锁 ,你可以确定递归“自死锁”永远不会发生。所以,这是最好和最便宜的解决方案。
  • 如果您要添加其他“同步”方法,当互斥量已经通过调用线程持有时调用当前方法,那么(并且仅在这种情况下)您确实需要替换 std::mutex 类型为 std::recursive_mutex .
  • 关于c++ - 带有重复参数的 Scoped_lock,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67356331/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com