#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>

pthread_mutex_t resource[5];
char res_str[] = "00000";

int pick(){return rand()%5;}
int pick2(){return rand()%2+1;}

void* t1 (void * p) {
  int r1, r2;
  while(1) {
    r1=pick(); r2=pick();
    sleep(pick2());
    pthread_mutex_trylock(&resource[r1]); //jag har bytt till trylock istället för pthred_mutex_lock.
    res_str[r1]='1';
    pthread_mutex_trylock(&resource[r2]); //jag har bytt till trylock istället för pthred_mutex_lock.
    res_str[r2]='1';
    sleep(pick2());
    res_str[r1]='0';
    res_str[r2]='0';
    pthread_mutex_unlock(&resource[r1]);
    pthread_mutex_unlock(&resource[r2]);
  }
}

void* t2 (void * p) {
  int r1, r2;
  while(1) {
    r1=pick(); r2=pick();
    sleep(pick2());
    pthread_mutex_trylock(&resource[r1]); //jag har bytt till trylock istället för pthred_mutex_lock.
    res_str[r1]='2';
    pthread_mutex_trylock(&resource[r2]); //jag har bytt till trylock istället för pthred_mutex_lock.
    res_str[r2]='2';
    sleep(pick2());
    res_str[r1]='0';
    res_str[r2]='0';
    pthread_mutex_unlock(&resource[r1]);
    pthread_mutex_unlock(&resource[r2]);
  }
}

main() {
  int i=0,n;
  pthread_t id1, id2;
  pthread_create(&id1,NULL,&t1,NULL);
  pthread_create(&id2,NULL,&t2,NULL);
  while(i++<30)
  {
    sleep(1);
    printf("%2d: %s\n", i, res_str);
  }
}


/*Efter den lilla modifikationen av programmet nämligen 
bytet från pthread_mutex_lock() till pthread_mutex_trylock(), 
så kan vi nu med säkerhet
säga att deadlock inte uppstår igen. Detta innebär att 
båda trådarna inte kommer behöva stå och vänta på 
varandra i en cirkulär
struktur. Innan modifikationen då trådarna använde 
sig av metoden pthread_mutex_lock() gjorde så att båda 
trådarna blev blockerade för att
vänta tills den andra tråden släpper resursen. Detta 
medförde ofta till deadlock i programmet, vilket är 
nu fixat med bytet till metoden
pthread_mutex_trylock().

En av de viktigaste vilkoren för att undvika deadlocks är just att bryta den cirkulära väntan. Detta betyder alltså att 
trådarna inte skall
bli blockerade medan de väntar på att andra resuerser 
blir lediga. Syftet med pthread_mutex_trylock() metoden 
är framför allt att undvika
blockeringen av tråden som vill komma åt en låst resurs.
Till skillnad från pthread_mutex_lock() som gör att 
tråden blir blockerad tills
den får tillgång till resursen. Avslutningsvis så kan man 
säga att pthread_mutex_trylock() testar om resursen är 
tillgänglig och därefter
försöker låsa den. om detta inte går så blir inte tråden 
blockerad utan den kommer att försöka då och då tills 
den får tillgång till resursen.
Detta bryter den cirkulära väntan och resulterar till 
att inga deadlock uppstår i programmet.



