In C ++, in order to block threads, I would recommend using state variables, not semaphores. In C #, monitors may be more appropriate.
Even for a fairly simple case, the manufacturer-consumer problem is more difficult to solve semaphores correctly: doing semaphore increments and losses in the wrong order can lead to problems. On the contrary, a solution based on variable variables will not have such problems: condition variables are used with a lock (mutex), and the correct order of operations is automatically applied; therefore, after waking up, the thread already has a detected lock.
See also my address. When should I use semaphores? , where I gave another example of a condition variable, in my opinion, more suitable for a problem often solved with semaphores.
And to solve another issue, I think that a higher responsibility for the erroneous use and more complex work of solutions (compared to alternatives) is the reason that some semaphores are not provided by some streaming packages. For TBB, I can say for sure. Thread support in C ++ 11 (developed after Boost.Thread) also does not; see Anthony Williams answer why.
source share