Edu*_*yan 7 c++ multithreading mutex deadlock c++11
继续使用Concurrency In Action我已经达到了以下示例.
Tha作者说,如果我们每次都以相同的顺序锁定2个互斥锁,那么我们可以保证避免死锁.
从书中考虑这个例子:
class X
{
private:
some_big_object some_detail;
std::mutex m;
public:
X(some_big_object const& sd):some_detail(sd){}
friend void swap(X& lhs, X& rhs)
{
if(&lhs==&rhs){return;}
std::lock(lhs.m,rhs.m);
std::lock_guard<std::mutex> lock_a(lhs.m,std::adopt_lock);
std::lock_guard<std::mutex> lock_b(rhs.m,std::adopt_lock);
swap(lhs.some_detail,rhs.some_detail);
}
};
Run Code Online (Sandbox Code Playgroud)
std::lock,然后应用2 std::lock_guards用std::adopt_lock,而不是仅仅使用2 std::lock_guards此起彼伏? std::mutexes放在std::scoped_lock??std::lock不是 RAII。不在 RAII 中的互斥锁是危险且可怕的。如果抛出异常,您可能会“泄漏”锁。
std::lock_guard不支持死锁安全的多重互斥锁。但它是 RAII,因此它使其余代码更安全。如果您在一个位置锁定 a,然后锁定 b,然后在另一个位置锁定 b,然后锁定 a,则会得到可能发生死锁的代码(一个线程持有 a 并等待 b,另一个线程持有 b 并等待 a)。
std::lock保证通过某种未指定的方式(可能包括锁的全局顺序)来避免这种情况。
std::scoped_lock是c++17。在c++17中,您应该使用它来代替您显示的示例代码。添加它是因为编写该代码很糟糕。名称修改和链接问题阻止了简单地向现有锁定原语(例如锁保护)添加可变支持,这就是它具有不同名称的原因。
为什么我们应用std :: lock然后用std :: adopt_lock应用2 std :: lock_guards而不是一个接一个地应用2 std :: lock_guards?
如果你使用了两个std::lock_guard没有std::lock锁定顺序,a = b;则会与s 相反b = a;,其中a和b是Xs.如果一个线程尝试a = b;而另一个线程尝试b = a;它们可能会死锁.第一个线程将拥有锁定a的互斥锁并等待,b而第二个线程将拥有锁定b的互斥锁并等待a.使用std::lock确保锁定顺序始终一致.
为什么我们不能把这个2 std :: mutexs放在std :: scoped_lock中?
如果查看您链接的文章的发布日期,则c ++ 17尚不存在.由于std::scoped_lock是由c ++ 17引入的,因此无法在文章中使用它.这种锁定问题是std::scoped_lock要解决的设计,应该在现代代码中使用.