Semaphores are simple and elegant and allow the solution of many interesting problems. They do a lot more than just mutual exclusion. Show why there can never be more than one process buying milk at once. They are implemented in the same way as regular semaphores except multiple V's will not increase the semaphore to anything greater than one. Embody both exclusion and waiting.
Correctness is easy to determine.
Work with many processes. Can have many different critical sections with different semaphores. Can permit multiple processes into the critical section at once, if that is desirable. A synchronization kernel is appropriate for one layer. Semaphores can be used for things other than simple mutual exclusion.