Abstractly, a semaphore is a lock with a number of permits associated with it. Semaphores support two operations:
- Up, which increases the number of permits, and
- Down, which attempts to decrease the number of permits. If insufficient permits are available, then this operation waits until enough are available.
There are many ways to implement semaphores. Typically, though, semaphores are not implemented as spinlocks, and actually have the OS block the thread and have it sleep until the requested permit becomes available. That said, a perfectly legal implementation of a semaphore could have it busy-wait; I'm just not aware of any implementations that do this.
Condition variables represent a different concept. Typically, semaphores are designed to manage a resource where only so many copies exist. Each thread that wants the resource waits until the semaphore guarding access to it becomes available, and each thread using the resource owns one permit. Condition variables are typically used to allow threads to wait for certain events to occur. They usually support the operations
- Wait, which blocks the thread until it is signaled,
- Notify, which tells one thread waiting on the condition variable that it can proceed, and
- Notify-all, which tells all threads waiting on the condition variable that they can proceed.
Condition variables and semaphores can (usually) be used interchangeably, with a suitable change to the design of the lock usage. However, sometimes semaphores are easier to work with, and sometimes condition variables are easier to work with, so we have both primitives available. Commonly, you'll choose to use one over the other because of the particular library or language you're using. For example, Java objects have built-in support for monitors (condition variables paired with a lock), so it's often useful to use condition variables in Java, though Java semaphores do exist. If you're programming in Windows, then semaphores are the preferred method of synchronization, though condition variables do exist.
Hope this helps!