Concurrency Primitives: Locks, Semaphores, and Channels
Concurrent programs share state across threads. The primitives for managing that shared state - mutexes, semaphores, and channels - each express a different model of coordination. Understanding the differences determines which bugs you create.