1
votes

I'm studying mutexes and deadlocks in c++ pthreads from http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html

I understood them but i stacked at a point. I didn't understand what is the problem of the below code. Can you explain it with simple and clear words please? I quoted from this site:

Mutex Deadlock: ... Be careful when applying two or more mutexes to a section of code. If the first pthread_mutex_lock is applied and the second pthread_mutex_lock fails due to another thread applying a mutex, the first mutex may eventually lock all other threads from accessing data including the thread which holds the second mutex. The threads may wait indefinitely for the resource to become free causing a deadlock. It is best to test and if failure occurs, free the resources and stall before retrying.

01  ...
02  pthread_mutex_lock(&mutex_1);
03  while ( pthread_mutex_trylock(&mutex_2) )  /* Test if already locked   */
04  {
05     pthread_mutex_unlock(&mutex_1);  /* Free resource to avoid deadlock */
06         ...
07     /* stall here   */
08     ...
09     pthread_mutex_lock(&mutex_1);
10  }
11  count++;
12  pthread_mutex_unlock(&mutex_1);
13  pthread_mutex_unlock(&mutex_2);
14  ...

Thanks in advance.

2
Why do you think there's a problem with that code? It looks more like it's supposed to be an example of how to avoid the described problem.Mike Seymour
I think that the code is correct but I didn't understand what it says in sentences, his sentences are so complex, thus i thought that the code contains some problem.metis
#Mike Seymour , I didn't understand anything from this sentence : "If the first pthread_mutex_lock is applied and the second pthread_mutex_lock fails due to another thread applying a mutex, the first mutex may eventually lock all other threads from accessing data including the thread which holds the second mutex. "metis

2 Answers

1
votes

Essentially if you need two mutexes to perform a task, mutex_1 and mutex_2, if thread_A grabs mutex_1 and thread_B grabs mutex_2, they are stuck in a deadlock because they are both waiting for the other mutex to become available, but they never will because the other is waiting too.

That is why you typically enforce an order that mutexes can be acquired. For example, you must acquire mutex_1 before attempting to acquire mutex_2. That way you can't have mutex_2 without first having mutex_1, so there is no chance to cause a deadlock.

     Thread_A                Thread_B
        |                       |
        |                       |
   lock(mutex_1)                |            // Thread_A got mutex_1
        |                       |
        |                  lock(mutex_2)     // Thread_B got mutex_2
        |                       |
        |                       |
  trylock(mutex_2)              |            // Thread_A wants mutex_2
        |                 trylock(mutex_1)   // Thread_B wants mutex_1
        |                       |

Due to the timing, these threads are now at a deadlock. Both are waiting for a mutex that they will never get, because the other thread won't unlock the mutex it is holding until it finishes its work.

In your code example, note that the first thing they do is lock mutex_1. They then spin on mutex_2 until that comes available. This is enforcing the order mutex_1 then mutex_2.

1
votes

If you lock one mutex, then wait for the second, the first is still locked, so no-one else can get it while you wait. That's quite bad, so maybe unlock the first mutex while you wait. The code shows how to do that.

If another thread has the mutex you're waiting for, and needs your mutex (which it shouldn't, unless the design is messed up), then that's very bad - both threads will wait for ever, causing a "deadlock" - and you'll definitely need to unlock the first while you wait.

But in that case, you should fix it properly (as the next section describes) - always lock the two mutexes in a well-defined order.