Condition Variables
Condition variables allow threads to wait efficiently until a specific condition becomes true. Unlike mutexes, which provide mutual exclusion, condition variables coordinate thread execution by allowing waiting threads to sleep until another thread signals that the required condition has changed.
Learning Objectives
- Understand condition variables.
- Learn why waiting mechanisms are required.
- Understand signaling between threads.
- Study interaction between mutexes and condition variables.
- Prepare for POSIX condition variable APIs.
1. What is a Condition Variable?
A condition variable is a synchronization object that allows one or more threads to wait until a specific condition becomes true. Instead of repeatedly checking the condition in a loop, a waiting thread sleeps until another thread signals that the condition may now be satisfied.
2. Why Condition Variables are Needed
| Problem | Without Condition Variable |
|---|---|
| Waiting for Data | Continuous polling wastes CPU time. |
| Producer–Consumer | Consumer repeatedly checks for data. |
| Task Completion | Threads cannot efficiently wait. |
| Resource Availability | Busy waiting reduces performance. |
3. Busy Waiting
Busy waiting occurs when a thread repeatedly checks a condition without performing useful work. This wastes CPU cycles and reduces overall application efficiency. Condition variables eliminate unnecessary polling by allowing threads to sleep until notified.
4. Waiting and Signaling
5. Mutex and Condition Variable
A condition variable does not protect shared data. A mutex protects the shared resource, while the condition variable allows threads to wait for changes to that resource. Both synchronization objects are normally used together.
6. Producer–Consumer Model
7. pthread_cond_t
POSIX represents a condition variable using the
pthread_cond_t data type.
Applications declare one condition variable for each condition
that threads must wait for.
8. Condition Variable Lifecycle
9. Synchronization Roles
| Object | Responsibility |
|---|---|
| Mutex | Protect shared data. |
| Condition Variable | Coordinate waiting threads. |
10. Interview Questions
- What is a condition variable?
- Why are condition variables needed?
- What is busy waiting?
- How do condition variables improve CPU utilization?
- Why is a mutex required together with a condition variable?
- What is the producer–consumer problem?
- What is
pthread_cond_t? - Can a condition variable protect shared data?
- What is the difference between waiting and signaling?
- Describe the lifecycle of a condition variable.
11. Static Condition Variable Initialization
POSIX provides the
PTHREAD_COND_INITIALIZER macro for statically
initializing a condition variable with default attributes.
12. pthread_cond_init()
The pthread_cond_init() function initializes a
condition variable before it is used.
Passing NULL for the attribute parameter selects
the default condition variable attributes.
13. pthread_cond_destroy()
The pthread_cond_destroy() function releases the
resources associated with a condition variable.
The condition variable must not be in use when it is destroyed.
14. pthread_cond_wait()
The pthread_cond_wait() function causes the calling
thread to wait until another thread signals the condition.
The calling thread must own the associated mutex before invoking
this function.
While waiting, the mutex is automatically released.
Before the function returns, the mutex is automatically locked
again.
15. Waiting Sequence
16. pthread_cond_signal()
The pthread_cond_signal() function wakes one thread
that is currently waiting on the specified condition variable.
If no thread is waiting, the signal has no effect.
17. pthread_cond_broadcast()
The pthread_cond_broadcast() function wakes all
threads currently waiting on the specified condition variable.
Each awakened thread must compete to acquire the associated
mutex before continuing.
18. Signaling Sequence
19. Complete Initialization Example
20. Linux Commands
| Command | Description |
|---|---|
man pthread_cond_init |
Initialize a condition variable. |
man pthread_cond_wait |
Wait on a condition variable. |
man pthread_cond_signal |
Wake one waiting thread. |
man pthread_cond_broadcast |
Wake all waiting threads. |
man pthread_cond_destroy |
Destroy a condition variable. |
21. Interview Questions
- What is
PTHREAD_COND_INITIALIZER? - Why must a condition variable be initialized?
- Why must a mutex be locked before calling
pthread_cond_wait()? - What happens to the mutex while the thread is waiting?
- When is the mutex re-acquired?
- What is the difference between
pthread_cond_signal()andpthread_cond_broadcast()? - What happens if no thread is waiting when
pthread_cond_signal()is called? - Why do awakened threads compete for the mutex?
- When should
pthread_cond_broadcast()be used instead ofpthread_cond_signal()? - Describe the complete waiting sequence of a condition variable.
22. Producer–Consumer Example
The producer places data into a shared buffer and signals the condition variable. The consumer waits until data becomes available before reading the shared buffer.
23. Typical Waiting Loop
The condition is checked repeatedly because the thread must verify that the required condition is actually satisfied after returning from the wait function.
24. pthread_cond_timedwait()
The pthread_cond_timedwait() function waits for a
condition variable until either the condition is signaled or a
specified timeout expires.
25. Timed Waiting Sequence
26. Spurious Wakeups
A waiting thread may return from
pthread_cond_wait() or
pthread_cond_timedwait() even though the expected
condition has not become true.
For this reason, the condition should always be rechecked before
continuing execution.
27. pthread_condattr_t
Condition variable attributes are represented by the
pthread_condattr_t data type.
Applications may use attribute objects to configure condition
variables before initialization.
28. Attribute Lifecycle
29. Linux Commands
| Command | Description |
|---|---|
man pthread_cond_timedwait |
Timed wait for a condition. |
man pthread_condattr_init |
Initialize condition attributes. |
man pthread_condattr_destroy |
Destroy condition attributes. |
gdb ./program |
Debug multithreaded applications. |
strace ./program |
Trace system calls. |
30. Advanced Interview Questions
- What is the producer–consumer problem?
- Why should
pthread_cond_wait()normally be placed inside awhileloop? - What is a spurious wakeup?
- How does
pthread_cond_timedwait()differ frompthread_cond_wait()? - What happens if the timeout expires?
- What is
pthread_condattr_t? - When should timed waiting be preferred?
- Why should the condition be checked again after waking?
- What resources are protected by the mutex in the producer–consumer model?
- Describe the complete producer–consumer workflow using condition variables.
31. pthread_condattr_init()
The pthread_condattr_init() function initializes a
condition variable attribute object with default values.
Applications may modify the attributes before creating the
condition variable.
32. pthread_condattr_destroy()
The pthread_condattr_destroy() function releases the
resources associated with a condition variable attribute object.
After destruction, the attribute object should not be reused
unless it is initialized again.
33. Condition Variable Attribute Workflow
34. Complete Initialization Example
35. Best Practices
- Always associate a condition variable with the correct mutex.
- Protect the shared state using the mutex before checking the condition.
- Use a
whileloop when waiting for a condition. - Signal or broadcast only after updating the shared state.
- Keep critical sections as short as possible.
- Destroy condition variables when they are no longer needed.
- Always verify return values from POSIX thread functions.
36. Common Programming Mistakes
- Calling
pthread_cond_wait()without locking the associated mutex. - Using
ifinstead ofwhilewhen checking the condition. - Signaling a condition before updating the shared data.
- Destroying a condition variable while threads are still waiting.
- Ignoring return values from condition variable functions.
- Failing to protect shared data with a mutex.
- Holding the mutex longer than necessary.
37. Advanced Interview Questions
- What is the purpose of
pthread_condattr_t? - Why should condition variable attributes be initialized?
- When should
pthread_condattr_destroy()be called? - Why is a
whileloop recommended aroundpthread_cond_wait()? - What is the correct order for updating shared data and signaling a condition?
- What problems can occur if the associated mutex is not used correctly?
- Why should condition variables be destroyed before program termination?
- How do condition variables improve CPU efficiency compared to busy waiting?
- Explain the complete lifecycle of a condition variable.
- Describe the interaction between mutexes and condition variables.
38. Module Summary
In this module, we studied POSIX condition variables and their role in thread synchronization. We covered waiting and signaling mechanisms, producer–consumer coordination, timed waiting, spurious wakeups, condition variable attributes, initialization, destruction, and best practices. Condition variables allow threads to wait efficiently for state changes while mutexes continue to provide mutual exclusion for shared data.
Concept Mastery Assessment — Module 49
Verify your conceptual understanding with 12 targeted technical assessment questions. Instant feedback and explanations are provided for every choice.