Questa è una delle più vecchie primitive di sincronizzazione nella storia dell'informatica, inventata dallo scienziato olandese Edsger W. Dijkstra (egli usava P() e V() invece di acquire() e release()).
Un semaforo manipola un contatore interno che viene decrementato da ogni chiamata ad acquire() ed incrementato da ogni chiamata a release(). Il contatore non può mai andare sotto lo zero; quando acquire() lo trova a zero, si blocca, aspettando che qualche altro thread chiami release().
[value]) |
1
.
[blocking]) |
Quando invocato senza argomenti: se il contatore interno è più grande di zero all'entrata, lo decrementa di uno e termina immediatamente. Se è zero all'entrata, si blocca, aspettando sino a che qualche altro thread abbia chiamato release() per renderlo più grande di zero. Ciò viene fatto con un interlocking appropriato così che se più chiamate ad acquire() sono bloccate, release() ne risveglierà esattamente una. L'implementazione ne può prendere uno a caso, perciò non si può fare affidamento sull'ordine nel quale i thread bloccati vengono risvegliati. Non viene restituito alcun valore in questo caso.
Quando viene invocato con blocking impostato a vero, fa le stesse cose di quando viene chiamato senza argomenti, e restituisce vero.
Quando viene invocato con blocking impostato a falso, non si blocca. Se una chiamata senza un argomento si bloccherebbe, restituisce falso immediatamente; altrimenti, fa la stessa cosa di quando viene chiamato senza argomenti, e restituisce vero.
) |