Note: This question concerns C++11. The answer to the same question in C++17 (or later revisions) may have changed. For details:
注意:此问题与C++11有关。C++17(或更高版本)中对同一问题的答案可能已更改。有关详情,请访问:
When we want to lock multiple std::mutex
'es, we use std::lock()
. But std::lock()
does not provide RAII feature.
当我们想要锁定多个std::mutex时,我们使用std::lock()。但是std::lock()不提供RAII功能。
When we want to lock a std::mutex
in RAII way, we use std::lock_guard
. But std::lock_guard
cannot lock multiple std::mutex
'es safely.
当我们想要以RAII方式锁定std::mutex时,我们使用std::lock_Guard。但是std::lock_Guard不能安全地锁定多个std::mutex。
Is there any way to take the advantages of both methods, to lock multiple std::mutex
'es in RAII way?
有没有办法利用这两种方法的优点,以一种简单的方式锁定多个std::mutex?
更多回答
优秀答案推荐
Yes, you can use a std::unique_lock
with std::defer_lock
. It tells the unique_lock to not lock the mutex immediately, but to build the RAII wrapper.
可以,您可以将std::Unique_lock与std::defer_lock一起使用。它告诉UNIQUE_LOCK不要立即锁定互斥锁,而是构建RAII包装器。
std::unique_lock<std::mutex> lk1(mutex1, std::defer_lock);
std::unique_lock<std::mutex> lk2(mutex2, std::defer_lock);
std::lock(lk1, lk2);
Due to its variadic nature std::lock
is not bound to only two arguments but can be used with as many arguments as your compiler has support for.
由于它的可变性质,std::lock不仅绑定到两个参数,而且可以与编译器支持的任意多个参数一起使用。
Howard Hinnant also pointed out an interesting fact about performance, you can check this link if you are interested. He addresses performance concerns and shows that std::lock
can be implemented efficiently, I can also recommend to read all the comments in that post.
霍华德·辛纳特还指出了一个关于性能的有趣事实,如果你感兴趣,可以查看这个链接。他解决了性能问题,并展示了Std::Lock可以有效地实现,我还可以推荐阅读该帖子中的所有评论。
As you've pointed out, std::lock_guard
in itself doesn't provide a deadlock-free way of locking multiple mutexs. Without a safe method, you run into the Dining Philosophers Problem.
正如您所指出的,std::lock_guard本身并不提供锁定多个互斥锁的无死锁方式。如果没有一个安全的方法,你就会遇到吃饭哲学家问题。
std::lock
implements a deadlock-free algorithm which locks multiple Lockable objects.
It can be used with
Lock实现了一种无死锁的算法,该算法锁定多个可锁定对象。它可以与
std::mutex m1, m2;
{ // Option A - lock mutexes first, adopt later
std::lock(m1, m2);
std::lock_guard<std::mutex> lock1(m1, std::adopt_lock);
std::lock_guard<std::mutex> lock2(m2, std::adopt_lock);
// critical section ...
}
{ // Option B - defer first, lock locks later
std::unique_lock<std::mutex> lock1(m1, std::defer_lock);
std::unique_lock<std::mutex> lock2(m2, std::defer_lock);
std::lock(lock1, lock2);
// critical section ...
}
{ // Option C - std::scoped_lock (C++17, but provided here for completeness)
std::scoped_lock lock(m1, m2);
}
If you don't need the extra features that std::unique_lock
provides (e.g. transferring ownership of the lock elsewhere), then std::lock_guard
should be preferred.
如果您不需要std::only_lock提供的额外功能(例如,将锁的所有权转移到其他地方),那么应该首选std::lock_Guard。
Note: the examples show only two locks, but all methods work with arbitrarily many locks.
注意:示例中只显示了两个锁,但所有方法都可以处理任意多个锁。
更多回答
我是一名优秀的程序员,十分优秀!