NFP227 (TRA)
2007/2008
Synchronisation à l’aide des sémaphores et des moniteurs
Samia Bouzefrane Laboratoire CEDRIC Conservatoire National des Arts et Métiers http://cedric.cnam.fr/~bouzefra
1
NFP227 (TRA)
2007/2008
Exercice 1 : RDV à n processus Soient N processus parallèles ayant un point de rendez-vous. Un processus arrivant au point de rendez-vous se met en attente s'il existe au moins un autre processus qui n'y est pas arrivé. Le dernier arrivé réveillera les processus bloqués. La solution suivante résoud ce problème en utilisant des sémaphores.
Contexte commun: sémaphore mutex = 1, s= 0; entier NbArrivés = 0; /* nbre de processus arrivés au rendez-vous */ Procédure RDV Début P(mutex); NbArrivés = NbArrivés + 1; Si (NBArrivés < N) Alors /* non tous arrivés */ V(mutex); P(s);
/* on libère mutex et */ /* on se bloque */
Sinon V(mutex);
/* le dernier arrivé libère mutex et */
Pour i = 1 à N-1 Faire V(s); /* réveille les N-1 bloqués, dans l'ordre d'arrivée */ Finsi Fin Question : Traduire cet algorithme en C ensuite en Java en utilisant les sémaphores. Exercice 2 : Nous nous intéressons au problème d’allocation de ressources banalisées. Nous supposons disposer dans un système de plusieurs exemplaires d’une même ressource, dont un nombre quelconque peut être demandé par un processus à un moment donné. Pour simplifier, nous considérons un seul type de ressource. Tout processus actif qui demande des exemplaires de cette ressource, doit solliciter les services d’un allocateur via deux procédures : - request(m) : pour demander l’allocation de m exemplaires de la ressource - release(m) : pour libérer les m exemplaires de la ressource L’allocateur maintient une variable critique qui compte le nombre d’exemplaires disponibles afin de satisfaire éventuellement de nouvelles demandes. Contexte commun : entier NbRessDisponibles :=Max ; Comportement d’un processus : While (true) { request(m) ; utiliser les m ressources release(m) ;
2
NFP227 (TRA)
2007/2008
} Procédure request (entier m) { Tant que (NbRessDisponibles
3
NFP227 (TRA)
2007/2008
Solution Exercice 1 : Solution du RDV à n processus en utilisant les sémaphores Java 1.5 import java.util.concurrent.*; // classe RendezVous class RendezVous { private int nbArrives; int N; Semaphore s; Semaphore mutex; RendezVous(int MaxProcess) { nbArrives = 0; s= new Semaphore(0,true); mutex= new Semaphore(1,true); N=MaxProcess; } public void proc_rdv() throws InterruptedException { mutex.acquire(); nbArrives=nbArrives+1; if (nbArrives < N) { mutex.release(); System.out.println(Thread.currentThread().getName() + " se bloque ") ; s.acquire(); } else { mutex.release(); System.out.println(Thread.currentThread().getName() + " est le dernier, il reveille les autres processus ") ; for (int i=1;i<=N-1; i++) s.release(); } }// fin proc_rdv
} // fin de la classe RendezVous // classe Processus class Processus extends Thread { RendezVous rv; Processus(RendezVous rv) { this.rv=rv;} public void run() { try { Thread.sleep(1000*(int)Math.random()) ; rv.proc_rdv() ; Thread.sleep(6000*(int)Math.random()) ;
} catch(InterruptedException e) {} } // fin de run() } // fin de la classe Processus // classe principale (main) class RDVMain { // a lancer avec le nb de processus total public static void main(String argv[]) { int N =Integer.parseInt(argv[0]); RendezVous rv= new RendezVous(N); Processus process[]= new Processus[N] ;
4
NFP227 (TRA)
2007/2008
for (int i=0 ; i
Processus0 Processus6 Processus1 Processus9 Processus8 Processus7 Processus5 Processus4 Processus3 Processus2 $ */
se bloque se bloque se bloque est le dernier, il reveille les autres processus se bloque se bloque se bloque se bloque se bloque se bloque
Exercice 2 /* allocation.c */ #include
#include #define NbTh 5 ressources */ #define M 100
/*Nombre de threads symbolisant les demandeurs de
pthread_t tid[NbTh]; pthread_mutex_t mutex; pthread_cond_t condRessNonDispo; // variable critique int NbRessDisponibles=M; void request(int m) { pthread_mutex_lock(&mutex); while(NbRessDisponibles < m) pthread_cond_wait(&condRessNonDispo, &mutex); printf("Le demandeur %d alloue %d ressources\n", pthread_self(),m); NbRessDisponibles = NbRessDisponibles - m; printf("Le nb de ress disponibles %d \n", NbRessDisponibles); pthread_mutex_unlock(&mutex); }
void release(int m) { pthread_mutex_lock(&mutex); printf("Le demandeur %d libere %d ressources\n",pthread_self(),m); NbRessDisponibles = NbRessDisponibles + m; printf("Le nb de ress disponibles %d \n", NbRessDisponibles);
5
NFP227 (TRA)
2007/2008
pthread_cond_broadcast(&condRessNonDispo); pthread_mutex_unlock(&mutex); }
void * Demandeur(void ) { int j; srand(pthread_self()); j=rand()%100; request(j); /* temps d'utilisation */ printf("Le demandeur %d utilise les ressources\n", pthread_self()); usleep(rand()%200000); release(j); }
int main() { int num; pthread_mutex_init(&mutex,0); pthread_cond_init(&condRessNonDispo,0); //creation des threads for(num=0;num
6