This post doesn't contain any new information or clever opinions. It simply points out a few articles published elsewhere that this humble author suspects his readers will find relevant. (Members of the Embedded group on LinkedIn may have seen some of these articles already, but they have relevance to any multi-threaded system, embedded or not.)
Many developers suffer from confusion with respect to the differences between mutexes and semaphores. Michael Barr of Netrino provides solid information in his article Mutexes and Semaphores Demystified. My summary: mutexes protect shared resources by enforcing mutual exclusion; semaphores should be used for signaling across tasks.
Niall Cooling of Feabhas provides a longer discussion in two parts:
Cooling focuses especially on the problems that arise when developers use semaphores where they should rather use mutexes. In particular, he discusses accidental lock release, various causes of deadlock, and priority inversion. (The latter is of special interest to developers of real-time software.)
Although semaphores and mutexes are critical concurrency-control structures, the APIs to use them unfortunately differ from platform to platform with respect to both form and function. At the end of his Part 2, Cooling briefly summarizes some of the differences between the semaphore and mutex APIs of several operating systems. This section will be of interest to anyone developing systems that will be ported across very different platforms. Chris Simmonds goes into more depth, with respect to Linux in particular, in his article Mutex mutandis: understanding mutex types and attributes posted on The Inner Penguin.