/* first_mutex and second_mutex are created and initialized. */ T1 waits on first_mutex; /* T1 holds first_mutex */ T2 waits on second_mutex; /* T2 holds second_mutex */ T1 waits on second_mutex; /* T1 has blocked */ T2 waits on first_mutex; /* T2 has blocked */Now both threads are blocked forever - deadlocked. Notice that the deadlock described above happens only if the two threads interleave their actions in a specific way. For example, if T2 first executes all of the code in function do_work_two(), and then T1 executes all of the code in function do_work_one(), there is no adverse result. In that case, first T2 acquires both locks, then does some work, then releases both locks; and after that T1 acquires both locks, does some work, and releases both locks.
/* thread_one runs in this function */ void *do_work_one(void *param) { int done = 0; while (!done) { pthread_mutex_lock(&first_mutex); if (pthread_mutex_trylock(&second_mutex)) { /* Do some work */ pthread_mutex_unlock(&second_mutex); pthread_mutex_unlock(&first_mutex); done = 1; } else pthread_mutex_unlock(&first_mutex); } pthread_exit(0); } /* thread_two runs in this function */ void *do_work_two(void *param) { int done = 0; while (!done) { pthread_mutex_lock(&second_mutex); if (pthread_mutex_trylock(&first_mutex)) { /* Do some work */ pthread_mutex_unlock(&first_mutex); pthread_mutex_unlock(&second_mutex); done = 1; } else pthread_mutex_unlock(&second_mutex); } pthread_exit(0); }
thread max needs cur alloc needs left free T0 10 5 5 3 T1 4 2 2 T2 9 2 7There's one resource type (tape drives, say) with twelve instances, allocated as shown. The threads have the indicated max possible needs and remaining needs. The system shown above is safe. {T1,T0, T2} is a safe sequence - the threads could finish executing in that order, even if all the threads first request all of their remaining needs. However, suppose that, starting from the situation depicted in the table above, T2 requests and is given one more tape drive. Then the state changes to this one:
thread max needs cur alloc needs left free T0 10 5 5 2 T1 4 2 2 T2 9 3 6This system is unsafe. If all the threads request their remaining needs, the system will be deadlocked. It will be possible for the OS to give T1 its remaining needs, and possible for T1 to finish and exit. However, after that there will be only 4 tape drives free, and so both T0 and T2 are set up to wait forever.