Typowy semafor implementowany jest jako zmienna typu całkowitego. Semafory dzieli się na binarne i ogólne. Semafor binarny może przyjmować wartości binarne czyli 0 lub 1, ogólny - przyjmuje wartości większe bądz równe 0. Modyfikacja wartości semafora jest możliwa za pomocą trzech operacji: inicjalizacji, podnoszenia semafora "wait" ("P") oraz opuszczania "signal" ("V"). Dwie ostatnie muszą być realizowane nieprzerwanie - atomowo, programista musi zagwarantować niepodzielność tych funkcji, oznacza to że tylko jeden wątek może wykonywać tą funkcje. Funkcje są przeciwstawne aby uniknąć jednoczesnego sprawdzenia i modyfikacji przez więcej niż jedno zadanie.
wait(Semafor s) /* operacja atomowa */ { jeżeli s < 0 { czekaj /* warunek nie spełniony*/ } s = s - 1 } signal(Semafor s) /* operacja atomowa */ { s = s + 1 } Init(Semafor s, Całkowitoliczbowe v) { s = v }
Litery P i V zwykle są kojarzone ze słowami holenderskimi: passeren (przejść), proberen (próbować), vryjgeven (zwolnić), verhoog (zwiększać).
Najczęstszym zastosowaniem jest synchronizacja dostępu do zasobów systemowych współdzielonych przez kilka zadań, aby zapobiec problemom wynikającym z prób jednoczesnego dostępu i modyfikacji danego zasobu. Wyobraźmy sobie sytuacje kiedy na jednej drukarce jednocześnie operacji drukowania dokonywały by dwa programy efekt wydruku na pewno był daleki od zamierzonego.
Semafory są zwykle implementowane w obszarze jądra systemu operacyjnego. Pozwala to na zaawansowaną obsługę zadań chcących uzyskać dostęp do zasobu:
- wstrzymywanie ich do czasu zwolnienia semafora powiązanego z danym zasobem,
- wznowienie pracy zadania oczekującego na semaforze,
- utrzymywania semafora nawet po zakończeniu zadania, który go utworzyło.
« poprzednia |
---|