Many locks with a mutex and the ability to lock

I am new to threads and trying to understand a mutex. I understand the mutex as some object (key) that is selected by only one thread (if it is selected, then other threads cannot select it and have to wait) to access some part of the code that we want to block.
So only one thread has access to this blocked part of the code at a time (for example, a common counter). The rest of the threads will have to wait until the mutex is unlocked, etc.

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 a few mutex locks?
Will both mutex be selected by the same thread? I also read that multiple mutex locks can cause a deadlock.
Can someone explain and provide me an example of how I can cause a deadlock by blocking part of the code with two mutexes?

+5
source share
3 answers

A thread may contain several locks, yes. And a dead end can occur even if it has acquired only one mutex. Take a look at the workflow:

Theme A

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

Theme B

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

Theme A

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

DEAD END!

Reading this , some types of mutexes, such as PTHREAD_MUTEX_NORMAL , can also cause a thread to hang.

 . . . lock mutex . . . try lock 
+3
source

Here's a safe way to encode 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 cannot block, because std::lock(Mutex1, Mutex2) blocks both mutual accesses, avoiding a deadlock (according to some internal algorithm). The advantage of using std::lock is that you do not need to remember what order you need to lock your mutexes (which simplifies maintenance in a large code base). But the disadvantage is that you need to lock both locks at the same point in your code. If you cannot block them at the same time, then you need to go back to order, as the other answers describe.

This code is also safe for exceptions, because if any exception is thrown anywhere, anything that can be blocked will be unlocked as the exception is thrown.

+3
source

What happens if I write a few mutex locks? Will both mutex be selected on the same topic?

A thread can simultaneously hold any number of mutexes. In your code example, a thread entering an area protected by Mutex1 will try to get Mutex2 , waiting for another thread to exit first if necessary. In the code you present, there is no particular reason to think that it will fail.

I also read that multiple mutex locks can be deadlocked. Can someone explain to me how I can cause a deadlock blocking part of the code with 2 mutexes?

Suppose there are two threads, one of which contains mutex1, and the other contains mutex2 (in this case, at least the latter should run something different from your pseudo-code). Now suppose that each thread is trying to get a different mutex, not letting go of the one that it already has. The first thread must receive mutex2 in order to continue, and cannot do this until the other releases it. The second thread must get mutex1 to continue, and cannot do this until the other releases it. Ergo, not a single thread can go on - this is a dead end.

The general rule is the following: if there is a set of mutexes, all of which two or more threads may each of them want to conduct at the same time, then there must be a fixed relative ordering of these mutexes, which each thread performs when receiving any subset of them.

+2
source

Source: https://habr.com/ru/post/1265297/


All Articles