简体   繁体   English

具有互斥锁的多个锁和可能发生死锁

[英]Multiple locks with mutex and the possibility of a deadlock

I'm new to threads and trying to understand the mutex. 我是线程新手并试图理解互斥锁。
I understand mutex as some object ( key ) which is picked by only one thread ( if it's picked then the other threads can't pick it and have to wait ) to access some part of code which we want to lock. 我理解互斥锁是一个只被一个线程挑选的对象(密钥)(如果它被挑选然后其他线程无法选择它并且必须等待)来访问我们想要锁定的代码的某些部分。
So only one thread has access to that locked part of code at the time ( for example shared counter ). 因此,当时只有一个线程可以访问该锁定的代码部分(例如共享计数器)。 The other threads will have to wait until mutex is unlocked and so on. 其他线程必须等到互斥锁解锁等等。

Mutex1.Lock();
 {
     Mutex2.Lock();
     {
          // Code locked by mutex 1 and 2.
     }
     Mutex2.Unlock();

     // Code locked by mutex 1.
 }
 Mutex1.Unlock();

What happens if I write multiple mutex locks? 如果我写多个互斥锁会发生什么?
Will both mutexes get picked by the same thread? 这两个互斥锁是否会被同一个线程选中? I also read that multiple mutex locks may cause deadlock. 我还读到多个互斥锁可能导致死锁。
Could anyone explain and provide me an example of how could I cause deadlock by locking part of code with 2 mutexes? 谁能解释并提供一个例子,说明如何通过用2个互斥锁锁定部分代码来导致死锁?

Here's the safe way to code what you describe: 以下是对您描述的内容进行编码的安全方法:

std::mutex Mutex1;
std::mutex Mutex2;

void
test()
{
    using namespace std;
    lock(Mutex1, Mutex2);  // no deadlock!
    lock_guard<mutex> lk1{Mutex1, adopt_lock};
    {
        lock_guard<mutex> lk2{Mutex2, adopt_lock};
        // Code locked by mutex 1 and 2.
    }   // lk2.unlock()
    // Code locked by mutex 1.
}   // lk1.unlock()

This code can't deadlock because std::lock(Mutex1, Mutex2) locks both mutexes while avoiding deadlock (by some internal algorithm). 此代码无法死锁,因为std::lock(Mutex1, Mutex2)锁定两个互斥锁,同时避免死锁(通过某些内部算法)。 An advantage of using std::lock is that you don't have to remember what order you need to lock your mutexes in (which makes maintenance easier in a large code base). 使用std::lock一个优点是您不必记住锁定互斥锁所需的顺序(这使得在大型代码库中维护更容易)。 But the disadvantage is that you need to lock both locks at a single point in your code. 但缺点是您需要在代码中的单个点锁定两个锁。 If you can't lock them at the same time, then you have to fall back to ordering as the other answers describe. 如果您无法同时锁定它们,那么您必须按照其他答案描述的那样回退到订购。

This code is also exception safe in that if any exception is thrown anywhere , whatever happens to be locked is unlocked as the exception propagates out. 此代码也是异常安全的,因为如果在任何地方抛出任何异常,则在异常传播时解锁任何被锁定的内容。

A thread can hold multiple locks, yes. 一个线程可以容纳多个锁,是的。 And a deadlock might occur indeed even if it has acquired only one mutex.. Look at the workflow: 即使它只获得了一个互斥锁,也可能发生死锁。查看工作流程:

Thread A 线程A.

. 
.
.
lock mutex1
.
<---- Context switch! ----->

Thread B 线程B.

.
.
.
.
lock mutex2
.
.
.
try lock mutex1 ----> BLOCKED UNTIL THREAD A RELEASES LOCK!

Thread A 线程A.

.
.
.
try lock mutex2 ---> BLOCKED UNTIL THREAD B RELEASES LOCK!

DEADLOCK! 僵局!

Read this , some mutex types, like the PTHREAD_MUTEX_NORMAL might cause a thread to deadlock it self as well. 读取这个 ,一些互斥体类型,如PTHREAD_MUTEX_NORMAL可能会导致线程自身死锁。

.
.
.
lock mutex
.
.
.
try lock

What happens if I write multiple mutex locks? 如果我写多个互斥锁会发生什么? Will both mutexes picked by the same thread? 这两个互斥锁是否会被同一个线程选中?

A thread can simultaneously hold any number of mutexes. 线程可以同时保存任意数量的互斥锁。 In your example code, a thread that enters the region protected by Mutex1 will attempt to acquire Mutex2 , waiting for another thread to release it first if necessary. 在您的示例代码中,进入受Mutex1保护的区域的线程将尝试获取Mutex2 ,等待另一个线程在必要时首先释放它。 There is no particular reason in the code you present to think that it would not succeed. 您提交的代码中没有特别的理由认为它不会成功。

I also read that multiple mutex locks may cause deadlock. 我还读到多个互斥锁可能导致死锁。 Could anyone explain me how could I cause deadlock by locking part of code with 2 mutexes? 任何人都可以解释我如何通过锁定部分代码与2个互斥锁导致死锁?

Suppose there are two threads, one holding mutex1 and the other holding mutex2 (in which case at least the latter must be running something different from your pseudocode). 假设有两个线程,一个持有mutex1而另一个持有mutex2(在这种情况下,至少后者必须运行与你的伪代码不同的东西)。 Now suppose that each thread attempts to acquire the other mutex without releasing the one it already holds. 现在假设每个线程都试图获取另一个互斥锁而不释放它已经拥有的互斥锁。 The first thread must acquire mutex2 to proceed, and cannot do so until the other releases it. 第一个线程必须获取mutex2才能继续,并且在另一个线程释放之前不能这样做。 The second thread must acquire mutex1 to proceed, and cannot do so until the other releases it. 第二个线程必须获取mutex1才能继续,并且在另一个线程释放之前不能这样做。 Ergo, neither thread can ever proceed -- this is a deadlock. 人机工程学, 两个线程不能继续-这是一个僵局。

The general rule is this: if there is a set of mutexes, all of which two or more threads may each want to hold similtaneously, then there must be a fixed relative ordering of those mutexes that every thread honors when acquiring any subset of them. 一般规则是这样的:如果有一组互斥体,所有两个或多个线程可能都想要同时保持,那么每个线程在获取它们的任何子集时都必须遵循这些互斥体的固定相对排序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM