Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

The point is that implementing a semaphore with a mutex and condition is very easy but more versatile. A semaphore only has a single integer internal state, a condition can guard any number of shares variables.

I see no reason to use semaphores in multithreaded programming because of this. They have no advantages over mutex and condition but are much more limited.



> The point is that implementing a semaphore with a mutex and condition is very easy but more versatile.

Agreed. An interesting exercise is to try the reverse: implementing a condition variable with a semaphore. It's not trivial to do correctly.

I teach OS, and I still cover semaphores, but I always tell the class that I don't think they are very useful. I spend much more time on condition variables.


They are useful, just not in multithreaded programming.

Overall I am quite disappointed at the level of education with parallelism and concurrency now that we're 15 years into the multi-core era, let alone in the years past. I'm constantly having issues with coworkers who are quite clueless in the topic, doing futile attempts in taking a textbook example and applying that to a real world problem (usually involving semaphores or trying to use atomics because "locks are hard").

It's equally frustrating to hear the "don't use locks, do CSP/message passing/concurrent collections/lock-free queues instead" cargo cult. Yes, that works for a class of problems but you still need locks to implement message passing (no excuse to not learn locking) and getting simple atomicity invariants right is as hard or harder than with locks.

It takes discipline and hard work to get multithreaded programming right but there are plenty of silver bullets and snake oil being pushed.


Are there any performance benefits of semaphores vs mutex/condition?


No. Not really.

Programs should be optimized for the uncontended case where a mutex and semaphore are pretty similar.

Some textbook toy problems are theoretically faster with semaphores but that's not really the case for practical problems.

The overhead of synchronization primitives isn't really a concern in practice.


There are two uses of synchronization primitives, those that should never wait (mutexes) and those that should always wait. The example of the latter is a work queue, where work threads need to wake up as fast as possible.

In that case, using semaphores or other "exotic" synchronization primitives (my favorite are Windows's manual-reset events) can help eliminate contention.

Problems with exiting threads are real. An often sufficient solution is to make the semaphore (or event) waiters "detached" and not care about them, while ensuring that the producers don't exit until their work has been completed.

As with other advanced multithreaded programming techniques, discipline is key, together with noticing, documenting and applying recurrent idioms.


Do you have an example of a case where a semaphore helps with high contention?

I would think that using a lock free atomic solution would win there, assuming the contention is high and consistent. Even if the semaphore is marginally faster than a mutex for the uncontended case, both will call into kernel for the contended case. That's 25 ns for uncontended and 150 us for contended. Ie. you could spin about 6000 times on the atomic operation and still win.

I agree with you that discipline and applying best practices without compromise is the way to solve multithreaded problems. Testing, verification and tooling need to be top notch or the result is something that works most of the time.


Not really contention, but for example a common event semaphore pattern for multiple producer/single consumer is on the consumer side

   Test condition (e.g. queue not empty)
   If false,
       Reset event
       Test condition again
       If false,
           Wait on event
The event stays set most of the time, which helps reducing cacheline bounces between the producers even if you don't have contention; so even if you use lock free atomic operations with optimistic spinning for the busy case, (event) semaphores can then still be used when the worker goes to sleep.

The event itself can be implemented as a mutex/condvar pair, alternatively, but that's pointless if you document what you are doing and do it consistently.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: