Sobes.tech
Middle

Care este diferența dintre un semafor și un mutex?

sobes.tech AI

Răspuns de la AI

Semaforul este un mecanism de sincronizare generalizat utilizat pentru a gestiona accesul la resurse limitate de către mai multe fire concurente. Acesta păstrează o valoare întreagă care scade atunci când se preia resursa și crește atunci când se eliberează. Dacă valoarea semaforului este zero, încercarea de a-l prelua blochează firul până când alt fir eliberează resursa. Poate fi utilizat pentru a limita numărul de fire care lucrează simultan.

Mutex (excludere mutuală) este un semafor binar care poate fi în stare blocată sau deblocat. Este folosit pentru a proteja secțiunile critice ale codului împotriva accesului simultan de către mai multe fire. Doar un fir poate prelua mutex-ul într-un moment dat. Firul care a preluat mutex-ul nu poate fi întrerupt de alt fir care încearcă să-l preia. Dacă se încearcă preluarea unui mutex blocat, firul va fi blocat până când acesta este eliberat.

Diferențe cheie:

Caracteristică Semafor Mutex
Tipul Mecanism de sincronizare generalizat Semafor binar (caz particular de semafor)
Valoare Întreg (>= 0) Binar (0 sau 1)
Scop Controlul accesului la resurse, limitarea firelor Protejarea secțiunilor critice, excludere mutuală
Proprietar Poate nu avea proprietar Are întotdeauna un proprietar (firul care l-a preluat)
Utilizare în iOS DispatchSemaphore Adesea implementat prin DispatchQueue.sync sau NSRecursiveLock în anumite scenarii

Exemplu de utilizare a unui mutex pentru protejarea unei secțiuni critice:

// În contextul GCD (Grand Central Dispatch)
let serialQueue = DispatchQueue(label: "com.example.criticalSection")

serialQueue.sync {
    // Secțiunea critică a codului
    // Doar un fir poate fi aici în orice moment
}

Exemplu de utilizare a unui semafor pentru limitarea sarcinilor paralele:

// În contextul GCD (Grand Central Dispatch)
let semaphore = DispatchSemaphore(value: 3) // Permite 3 sarcini în paralel

DispatchQueue.global().async {
    semaphore.wait() // Scade valoarea semaforului cu 1. Blochează dacă valoarea este 0.

    // Codul sarcinii paralele
    print("Sarcină în curs")

    Thread.sleep(forTimeInterval: 1) // Simulare de lucru

    semaphore.signal() // Crește valoarea semaforului cu 1. Deblochează firul de așteptare, dacă există.
    print("Sarcină finalizată")
}

// Se pot lansa mai multe astfel de blocuri. Doar 3 vor fi executate simultan.