För att få en deadlock krävs att tre villkor blir uppfyllda.

1: En cyklisk väntan måste ske.
2: Ingen tillbakatagning av resursen får ske.
3: Resursen får ej vara delbar.

Om minst en av villkoren inte gäller förekommer inte deadlock.

I programmet uppg3a är alla tre villkoren uppfyllda. Vi har en
 cyklisk väntan
som man kan se på raderna:

pthread_mutex_lock(&m1); sleep(1);
pthread_mutex_lock(&m2);

i trådfunktion tf1

och raderna:

pthread_mutex_lock(&m2); sleep(1);
pthread_mutex_lock(&m1);

i trådfunktion tf2

Detta betyder att tråd1 tar resurs m1, sover en sekund och tar sedan m2.
Tråd2 tar resurs m2, sover en sekund och tar sedan m1.

Skulle trådarna komma samtidigt skulle tråd1 ta m1 och sova. 
Tråd2 tar samtidigt m2 och sover. Därefter sker en deadlock
 då tråd1 försöker
ta m2 som ägs av tråd2 och tråd2 försöker ta m1 som ägs av tråd1.

Samma rader i koden visar även att trådarna inte gör en tillbakatagning av 
resursena. Manualsidan för pthread_mutex_lock säger:

The  mutex  object  referenced  by  mutex  shall  be  locked by calling
pthread_mutex_lock(). If the  mutex  is  already  locked,  the  calling
thread  shall  block until the mutex becomes available.

Eftersom båda trådarna har pthread_mutex_lock efter varandra på båda 
resurserna sker ingen säkerhetskoll. Som manualsidan säger kan den 
kallande tråden bara vänta tills mutexen blir tillgänglig. Men eftersom
båda trådarna väntar på varandra kommer detta aldrig att ske.

Den tredje villkoren uppfylls eftersom vi använder mutexar som inte är
delbara.

Även uppg3b har samma cykliska väntan som uppg3a och använder även icke-
delbara resurser. Den enda skillnaden uppg3b har är att den bryter mot 
villkor 2 på följande sätt:

i trådfunktion tf1 finns koden:

pthread_mutex_lock(&m1);
if(pthread_mutex_trylock(&m2)) {
  dur=choose(3); while(dur--) {thread=1; sleep(1);} thread=0;
  pthread_mutex_unlock(&m1); pthread_mutex_unlock(&m2);
}
else pthread_mutex_unlock(&m1);

och i trådfunktion tf2 finns koden:

pthread_mutex_lock(&m2);
if(pthread_mutex_trylock(&m1)) {
  dur=choose(3); while(dur--) {thread=2; sleep(1);} thread=0;
  pthread_mutex_unlock(&m1); pthread_mutex_unlock(&m2);
}
else pthread_mutex_unlock(&m2);

Manualsidan för pthread_mutex_trylock säger följande:

The   pthread_mutex_trylock()   function   shall   be   equivalent   to
pthread_mutex_lock(),  except  that  if  the mutex object referenced by
mutex is  currently  locked  (by  any  thread,  including  the  current
thread),  the  call  shall  return  immediately.

Trådarna tar sin första resurs men istället för att sedan fastna som i uppg3a
så försöker de ta sin andra resurs. Är resursen redan tagen får trådarna 
direkt svar om det som manualsidan säger och kan då ta åtgärder för att 
förhindra att deadlock sker. I uppg3b koden som man kan se längre upp så
tar trådarna sin första resurs och försöker ta den andra resursen. Är
resursen redan ägd så hamnar man under else och så släpper tråden sin första
resurs så att en annan tråd som väntar på den kan ta den och börja
arbeta med sin kritiska sektion. När tråden arbetat klart kallar den på
pthread_mutex_unlock som släpper resurserna. Tråden som var snäll och släppte
sin resurs kan sedan ta resurserna och börja arbeta med sin kritiska sektion. 
