###### tags: `prir` `studia`
# Problem ucztujących filozofów
Klasyczny problem synchronizacji
- pięciu filozofów
- 5 talerzy
- 5 widelców
- każdy filozof potrzebuje dwóch widelców żeby jeść (musi wziąć jednego z prawej i jednego z lewej)
- w danym momencie kazdy może podnieść jeden widelec, nie może dwóch na raz
> Jednocześnie może jeść maksymalnie dwóch filozofów którzy nie siedzą koło siebie (dla reszty zabraknie widelców)
## Rozwiązanie naiwne - które NIE DZIAŁA
```
Semaphore widelec[..4] = [(1, {})]
-> FILOZOF[i]
loop {
mysl()
wait(widelec[i])
wait(widelec[i+1]%5)
jedz()
signal(widelec[i])
signal(widelec[i+1]%5)
}
```
**Dochodzi do zagłodzenia!**
## Rozwiązanie ograniczające miejsca - poprawne
```
Semaphore widelec[0..4] = [(1, {})]
Semaphore sa_miejsca = (4, {})
-> FILOZOF[i]
loop {
mysl()
wait(sa_miejsca)
wait(widelec[i])
wait(widelec[i+1]%5)
jedz()
signal(widelec[i])
signal(widelec[i+1]%5)
signal(sa_miejsca)
}
```
## Rozwiązanie asymetryczne - podobne do naiwnego, ale łamiemy cykl podniesień widelca
```
Semaphore widelec[0..4] = [{1, ()}]
-> FILOZOF[i]
int p,q
if (i==0) p=(i+1)%5, q=i
else p=i, q=(i+1)%5
loop {
mysl()
wait(widelec[p])
wait(widelec[q])
jedz()
signal(widelec[p])
signal(widelec[q])
}
```
## Rozwiązanie asymetryczne z użyciem monitora
```
monitor WidelceFilozofow {
int widelce[0..4];
Condition mozeJesc[0..4]
void podnies(int filozof) {
if (widelce[filozof] < 2) wait(mozeJesc[filozof])
int prawy = (filozof-1)%n
int lewy = (filozof+1)%n
--widelce[prawy]
--widelce[lewy]
}
void poloz(int filozof) {
int prawy = (filozof-1)%n
int lewy = (filozof+1)%n
++widelce[prawy]
++widelce[lewy]
if (widelec[prawy] == 2) signal(mozeJesc[prawy])
if (widelec[lewy] == 2) signal(mozeJesc[lewy])
}
}
```