Sobes.tech
Middle

Cos'è un semaforo nel contesto della programmazione?

sobes.tech AI

Risposta dell'AI

Il semaforo è una primitive di sincronizzazione dei thread che controlla l'accesso a una risorsa limitata. Tiene traccia di un contatore intero.

Operazioni principali:

  • wait() (o P / acquire) : Diminuisce il contatore di 1. Se il contatore diventa negativo, il thread viene bloccato fino a quando un altro esegue signal().
  • signal() (o V / release) : Aumenta il contatore di 1. Se ci sono thread bloccati, uno di essi viene sbloccato.

Tipi di semafori:

  • Semaforo binario (mutex) : Il contatore assume valori 0 o 1. Usato per garantire l'esclusione mutua: solo un thread può accedere alla risorsa alla volta.
  • Semaforo contatore : Il contatore può assumere valori da 0 a N. Usato per gestire l'accesso a un pool di risorse con un numero limitato di elementi disponibili.

Esempio di utilizzo in Swift per limitare il numero di task che possono essere eseguiti contemporaneamente:

// Creazione di un semaforo che permette fino a 3 accessi simultanei
let semaphore = DispatchSemaphore(value: 3)

DispatchQueue.global().async {
    // Task 1
    semaphore.wait() // Diminuisce il contatore, blocca se > 3 task sono in esecuzione
    print("Task 1 avviato")
    Thread.sleep(forTimeInterval: 2) // Simulazione di lavoro
    print("Task 1 completato")
    semaphore.signal() // Aumenta il contatore, sblocca le task in attesa
}

DispatchQueue.global().async {
    // Task 2
    semaphore.wait()
    print("Task 2 avviato")
    Thread.sleep(forTimeInterval: 3)
    print("Task 2 completato")
    semaphore.signal()
}

DispatchQueue.global().async {
    // Task 3
    semaphore.wait()
    print("Task 3 avviato")
    Thread.sleep(forTimeInterval: 1)
    print("Task 3 completato")
    semaphore.signal()
}

DispatchQueue.global().async {
    // Task 4 (attenderà finché non si libera uno slot)
    semaphore.wait()
    print("Task 4 avviato")
    Thread.sleep(forTimeInterval: 2)
    print("Task 4 completato")
    semaphore.signal()
}

// Attendere il completamento di tutte le task per la dimostrazione
// Usare meccanismi di attesa più affidabili nel codice reale
Thread.sleep(forTimeInterval: 5)