Sobes.tech
Middle

Jaka jest różnica między semaforem a mutexem?

sobes.tech AI

Odpowiedź od AI

Semafor to uogólniony mechanizm synchronizacji używany do zarządzania dostępem do ograniczonych zasobów przez wiele konkurencyjnych wątków. Przechowuje wartość całkowitą, która jest zmniejszana podczas przejęcia zasobu i zwiększana podczas zwolnienia. Jeśli wartość semafora wynosi zero, próba jego przejęcia blokuje wątek do czasu zwolnienia zasobu przez inny wątek. Może być używany do ograniczenia liczby jednocześnie działających wątków.

Mutex (mutual exclusion) to binarny semafor, który może znajdować się w stanie zablokowanym lub odblokowanym. Służy do ochrony sekcji krytycznych kodu przed równoczesnym dostępem wielu wątków. Tylko jeden wątek może przejąć mutex w danym momencie. Wątek, który przejął mutex, nie może zostać przerwany przez inny wątek próbujący go przejąć. Jeśli spróbujesz przejąć zablokowany mutex, wątek zostanie zablokowany do czasu zwolnienia.

Kluczowe różnice:

Charakterystyka Semafor Mutex
Typ Uogólniony mechanizm synchronizacji Binarny semafor (przypadek szczególny semafora)
Wartość Liczba całkowita (>= 0) Binarny (0 lub 1)
Przeznaczenie Zarządzanie dostępem do zasobów, ograniczanie liczby wątków Ochrona sekcji krytycznych, wzajemne wykluczanie
Właściciel Może nie mieć właściciela Zawsze ma właściciela (wątek, który go przejął)
Użycie w iOS DispatchSemaphore Często implementowany przez DispatchQueue.sync lub NSRecursiveLock w niektórych scenariuszach

Przykład użycia mutex do ochrony sekcji krytycznej:

// W kontekście GCD (Grand Central Dispatch)
let serialQueue = DispatchQueue(label: "com.example.criticalSection")

serialQueue.sync {
    // Sekcja krytyczna kodu
    // Tylko jeden wątek może tu być w danym momencie
}

Przykład użycia semafora do ograniczenia równoległych zadań:

// W kontekście GCD (Grand Central Dispatch)
let semaphore = DispatchSemaphore(value: 3) // Zezwala na 3 równoległe zadania

DispatchQueue.global().async {
    semaphore.wait() // Zmniejsza wartość semafora o 1. Blokuje, jeśli wartość wynosi 0.

    // Kod zadania równoległego
    print("Zadanie wykonywane")

    Thread.sleep(forTimeInterval: 1) // Symulacja pracy

    semaphore.signal() // Zwiększa wartość semafora o 1. Odblokowuje oczekujący wątek, jeśli taki jest.
    print("Zadanie zakończone")
}

// Można uruchomić kilka takich bloków. Tylko 3 będą wykonywać się jednocześnie.