7.

1 The sushi bar problem
Această problemă a fost inspirata de o problemă propusa de Kenneth Reek [9]. Imagina un bar sushi cu 5 locuri. Dacă ajungeţi în timp ce există un loc gol, puteţi lua un loc imediat. Dar dacă dumneavoastră atunci când toate cele 5 locuri sunt ocupate, ceea ce înseamnă că toti mananca impreuna, şi va trebui să aşteptaţi pe toti să plece înainte de a vă aşeza. Puzzle: scrie codul pentru clienţii care intră şi ies din bar sushi cu care impune aceste cerinţe.

7.1.1 Sushi bar hint
Aici sunt variabilele care le-am folosit:
Listing 7.1: Sushi bar hint 1 eating = waiting = 0 2 mutex = Semaphore(1) 3 block = Semaphore(0) 4 must_wait = False

mănâncă şi de aşteapta tine evidenta numărul de fire asezate la bar şi asteapta. mutex protejează ambele contoare. trebuie să aştepte indică faptul că barul este (Sau a fost) ocupat, clienţii ce vin a trebui sa fie blocati

7.1.2 Sushi bar non-solution
Aici este o solutie incorectă Reek folosita pentru a ilustra una din dificultăţile acestei probleme.
Listing 7.2: Sushi bar non-solution 1 mutex.wait() 2 if must_wait: 3 waiting += 1 4 mutex.signal() 5 block.wait() 6 7 mutex.wait() # reacquire mutex 8 waiting -= 1 9 10 eating += 1 11 must_wait = (eating == 5) 12 mutex.signal() 13 14 # eat sushi 15

face actualizarea. Puzzle: a se vedea dacă pot veni cu două soluţii corecte! Sugestie: nu foloseste nici un solution variabile suplimentare.3 Sushi bar non-solution Problema este la linia 7.4 Sushi bar solution #1 Singurul motiv pentru care un client are de aşteptat de a reachiziţiona the mutex este de a actualiza starea de aşteptare şi de a mănca. Listing 7. care încalcă sincronizarea constrângeri.wait() 6 else: 7 eating += 1 8 must_wait = (eating == 5) 9 mutex.wait() 2 if must_wait: 3 waiting += 1 4 mutex. astfel încât alţi clienţi pot pleca. acestea au pentru a obţine mutex înapoi.signal() . 7.wait() eating -= 1 if eating == 0: n = min(5. care are deja mutex. Reek oferă două soluţii la această problemă. Dar atunci când clienţii se trezesc. şi elimină must_wait.signal() 7. care se trezeşte cel puţin unel dintre clienţi care asteapta. care apar în următoarele douaS secţiuni.1.1. ea semnale de bloc.signal(n) must_wait = False mutex. În cazul în care ultimul client pleaca. astfel încât într-un fel de a rezolva problema este de a face ca clientul sa plece. şi înseamnă că trebuie să concureze cu noi fire primite. Dacă noi fire sosesc şi pentru a obţine mutex în primul rând. acestea ar putea avea toate locurile înainte de fire de aşteptare. Dacă un client soseşte în timp ce barul este ocupat.16 17 18 19 20 21 22 mutex. este posibil ca mai mult de 5 fire să fie în secţiunea critică în acelaşi timp. waiting) block. el trebuie să renunţe la mutex în timp ce el asteapta.signal() 5 block.3: Sushi bar solution #1 1 mutex. Aceasta nu este doar o chestiune de nedreptate.

10 11 12 13 14 15 16 17 18 19 20 21 # eat sushi mutex. astfel încât noi clienţii care sosesc au dreptul de a vedea starea şi blocul daca este necesar. un fir poate achiziţiona e un sistem de blocare şi apoi un alt fir se poate elibera. we have the mutex 6 waiting -= 1 7 8 eating += 1 9 must_wait = (eating == 5) 10 if waiting and not must_wait: 11 block.signal() 14 15 # eat sushi 16 17 mutex. pentru că pleacă thread este de a face de lucru care pare.wait() . Un dezavantaj al acestei abordări este că acesta este un pic mai dificila pentru a confirma că starea este actualizată în mod corect.5 Sushi bar solution #2 Soluţia alternativă al Reek-ului se bazează pe noţiunea contraintuitiva că putem transfera de la un mutex un fir la altul! Cu alte cuvinte.4: Sushi bar solution #2 1 mutex.wait() 2 if must_wait: 3 waiting += 1 4 mutex.wait() eating -= 1 if eating == 0: n = min(5.wait() # when we resume. Reek solicită acest model "o voi face pentru tine".signal(n) mutex.signal() Atunci când pleacă ultimul client elibereaza mutex. în mod logic. mâncând a fost deja actualizat.signal() # and pass the mutex 12 else: 13 mutex. nu este nimic în neregulă cu acest lucru.1. Atâta timp cât ambele fire inţeleg că blocarea a fost transferata. să aparţină firelor de aşteptare. waiting) waiting -= n eating += n must_wait = (eating == 5) block. Listing 7. 7.signal() 5 block.

h> #include<pthread. } else { eating+=1. sem_t block.n. sleep(3). void* sushi_bar(void* arg) { while(1){ int i.waiting=0.18 19 20 21 22 23 24 eating -= 1 if eating == 0: must_wait = False if waiting and not must_wait: block.signal() # and pass the mutex else: mutex. sem_wait(&block). if(eating==5) { waiting+=1.h> #define NR_DE_CLIENTI 5 pthread_t clienti [NR_DE_CLIENTI]. pthread_mutex_unlock(&mutex).*(int *)arg). printf(“asteapta client…%d\n”.h> #include<stdio. pthread_mutex_lock(&mutex). . pthread_mutex_unlock(&mutex). int eating=0.h> #include<stdlib. } printf(“clientul mananca…%d\n”.signal() Programul: #include<semaphore. pthread_mutex_t mutex.*(int *)arg).

waiting-=n. pthread_mutex_init(&mutex.i< NR_DE_CLIENTI.i< NR_DE_CLIENTI.0. for(i=0.&client_id[i]).0). } } main() { int i=0.i<n.*(int *)arg). else n=5.0. //block=make_semaphore(0).sushi_bar.0). if(eating==0 && waiting) { if (waiting<5) n=waiting.i++) sem_post(&block).i++) client_id[i]=i+1. //mutex=make_semaphore(1). printf(“\t Clientul a terminat de mancat…&d\n”. eating+=n. sleep(3). } pthread_mutex_unlock(&mutex).i++) pthread_create(&client[i]. sem_init(&block. int client_id[NR_DE_CLIENTI]. while(1). for(i=0. } .pthread_mutex_unlock(&mutex). eating-=1. for(i=0.

Sign up to vote on this title
UsefulNot useful