3 ms·
Semaphores are particularly treacherous on processors with weakly-ordered memory models (ARM and PowerPC notably). Condition variables are much easier to reaso
by rerdavies 4y ago
Semaphores are particularly treacherous on processors with weakly-ordered memory models (ARM and PowerPC notably).
Condition variables are much easier to reason about, because there are clear and unambiguous memory barriers around data being shared by sender and receiver threads; and semaphores are trivially implementable using condition variables if that's truly all you need.
On processors with weakly-ordered memory models, consecutive writes to memory by one thread may be seen as occurring in a different order on a receiver thread. On processor with a strongly-ordered memory model (Intel), you can sometimes update the state of data being controlled by the semaphore before set, and after wait by relying on strong ordering of reads and writes (although it is insanely easy to make a make mistakes that causes terrible bugs, and infamously difficult to determine whether you haven't made a mistake).
On weakly-ordered platforms this doesn't work so you almost always have to update the state of the controlled object before set, and after wait while holding a mutex. But if you're going to use both a mutex AND a semaphore, then you may as well use a condition variable instead.
Bottom line: if you use a semaphore on a processor with a weakly-ordered memory model, you are almost definitely doing it wrong; and if you use one on a processor with a strongly-ordered memory model, you are still probably doing it wrong.
As to efficiency -- I can't imagine there is a meaningful difference. And even if there is, having a much higher chance of doing it right surely makes up for it.
- gpderetta 4y agoIndeed, if your data need to be mutex protected might as well use a condition variable: it will be as efficient and certainly more understandable. Semaphore make sense for one shot publishing: write the data -> signal -> wakeup then read the data, where some other invariant prevents reading the data before the wait. They also work somewhat well to add waiting on otherwise lock free queues. In POSIX, condition variables are not async signal safe, so sem_t is a good alternative if needed. On linux mutexes are farily