chiamata verso il basso quando si tratta di 0 non dovrebbe funzionare. Chiamare quando è 3 funziona. (Sto pensando a Java).
Lasciatemi aggiungere altro. Molte persone pensano a serrature come i semafori (binari) (es. N = 1, quindi il valore del semaforo è 0 (tenuto) o 1 (non trattenuto)). Ma questo non è giusto. Una serratura ha una nozione di "proprietà", quindi potrebbe essere "rientrante". Ciò significa che un thread che contiene un lock, è autorizzato a chiamare lock() di nuovo (spostando efficacemente il conteggio da 0 a -1), perché il thread detiene già il lock e gli è consentito "reinserirlo". Le serrature possono anche essere non rientranti. Ci si aspetta che un portablocco chiami unlock() lo stesso numero di volte di lock().
I semafori non hanno alcuna idea di proprietà, quindi non possono essere rientranti, sebbene possano essere acquisiti quanti più permessi disponibili. Ciò significa che un thread deve bloccare quando incontra un valore pari a 0, finché qualcuno non incrementa il semaforo.
Inoltre, in quello che ho visto (che è Java), è possibile incrementare il semaforo maggiore di N, e anche questo ha a che fare con la proprietà: un semaforo non ha la nozione di proprietà in modo che qualcuno possa darlo di più permessi. A differenza di un thread, dove ogni volta che un thread chiama unlock() senza tenere un lock, si tratta di un errore. (In java genererà un'eccezione).
Spero che questo modo di pensarci sia d'aiuto.
Vedere anche http://stackoverflow.com/questions/184147/countdownlatch-vs-semaphore – finnw