
The Little Book of Semaphores (2016) [pdf] - kbp
http://greenteapress.com/semaphores/LittleBookOfSemaphores.pdf
======
exDM69
Semaphores are nice for text book examples, but should be avoided in practical
multi threaded programming in a shared memory environment. A mutex and
condition variables usually provides a cleaner solution that is easier to
reason about. In particular, the expression for the condition that's waited on
can be arbitrarily complex, not just a single integer like a semaphore's
internal state.

A particularly tricky problem is clean program termination when waiting on
semaphores. It is much easier to add while(!quit && not_satisfied)
cond_wait(lock, is_satisfied); than doing the same with semaphores. You need
to add extra synchronization for this case with semaphores. Every call to
cond_wait usually needs a check for a "quit" flag.

Semaphores are still useful in other kinds of asynchronous processes such as
CPU to GPU synchronization or keeping trains on railways from colliding.

If you encounter a semaphore in multi threaded code that's been written
recently, assume it is incorrect. That's the case in the past half a dozen
cases where I came across one in the codebase I work on. The most common bug
was the program hanging on exit. Replacing them with mutex and condition
variables (plural!) was easy, the solution was much simpler to understand and
it was correct and the programs now terminated cleanly when exit was
requested.

Semaphores should really be removed from the OS class curriculum. Maybe leave
them in the advanced parallel/concurrent programming course because they're
easy to reason about in formal proofs. But in multi threaded programming,
they're almost always the wrong tool for the job.

~~~
jeremiep
I believe semaphores and condition variables solve different problems.
Programs hanging at the exit only means the engineer mostly tested the happy
path, not that semaphores are evil. I've seen plenty of deadlocks on mutexes
at shutdown as well :)

~~~
exDM69
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.

~~~
anon946
> 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.

~~~
exDM69
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.

------
Dowwie
Alan is a great contributor to the Python community. He's dedicated countless
hours to tutorials and talks. @alan: If you're part of the HN community, as I
said once in person: thank you!

~~~
carapace
Do you mean Allen?

------
plandis
This looks like an updated version of the book that was written initially in
C?

------
xorblurb
This seems like an interesting book but a few points are dangerous, especially
if it is used for teaching.

1\. Concurrent access to a variable out of a critical section is qualified as
not being dangerous. This actually can't be decided without knowing about the
memory model you are considering, and both in the general case and in
practical implementations (C++) this is UB.

2\. This sentence is maybe only trying to be funny, but discouraging formal
proofs in 2016 can very well end up borderline criminal (depending on the
application): "The only alternative is to examine the code carefully and
“prove” that it is correct. I put “prove” in quotation marks because I don’t
mean, necessarily, that you have to write a formal proof (although there are
zealots who encourage such lunacy)."

Especially if this is stated right after a rather simple algorithm.

I can absolutely not recommend a book about a critical topic, which contains
that kind of defects.

~~~
yebyen
> in practical implementations (C++) this is UB.

Huh. I had heard of nasal demons before but I had never seen this abbreviation
"UB"

TIL, UB and IB

[https://stackoverflow.com/questions/2766731/what-exactly-
do-...](https://stackoverflow.com/questions/2766731/what-exactly-do-ib-and-ub-
mean)

