Sobes.tech
Middle

Na czym opierają się bariery i semafory?

sobes.tech AI

Odpowiedź od AI

Bariera i semafory w kontekście programowania równoległego opierają się na mechanizmach synchronizacji:

  • Semafory: Opierają się na operacjach atomowych na liczniku. Główne operacje:

    • wait (lub P, nabycie): Zmniejsza licznik. Jeśli licznik stanie się ujemny, wątek zostanie zablokowany do czasu wykonania signal przez inny wątek.
    • signal (lub V, zwolnienie): Zwiększa licznik. Jeśli są zablokowane wątki, jeden z nich zostanie obudzony.
    • Semafory mogą być binarne (wartość 0 lub 1, działają jak muteksy) lub licznikowe (pozwalają ograniczonej liczbie wątków na dostęp do zasobu).
  • Barierki: Opierają się na mechanizmie oczekiwania przez wszystkich uczestników. Wątek osiągający barierę zostaje zablokowany do czasu, aż wszystkie inne wątki zaangażowane w synchronizację również osiągną tę barierę. Po osiągnięciu przez wszystkie barierę, kontynuują równocześnie.

W rozwoju iOS/macOS te koncepcje są implementowane przy użyciu frameworków programowania współbieżnego, takich jak GCD (Grand Central Dispatch) i OperationQueue.

Na przykład, w GCD:

// Przykład użycia DispatchSemaphore
let semaphore = DispatchSemaphore(value: 1) // Semafor binarny

// Wait (nabycie)
semaphore.wait()
// Dostęp do sekcji krytycznej
semaphore.signal() // Signal (zwolnienie)

Barierki w GCD są realizowane za pomocą zadań barierowych (barrier tasks) dla kolejek współbieżnych:

let concurrentQueue = DispatchQueue(label: "com.example.concurrentQueue", attributes: .concurrent)

// Zadania zwykłe
concurrentQueue.async {
    // ...
}

// Zadanie barierowe - wykonywane tylko wtedy, gdy wszystkie poprzednie zadania zwykłe się zakończą
// I po tym, żadne nowe zadania nie rozpoczną się, dopóki to nie nastąpi
concurrentQueue.async(flags: .barrier) {
    // ...
}

// Zadania zwykłe, które rozpoczną się po zakończeniu zadania barierowego
concurrentQueue.async {
    // ...
}