condition_variable / shared variable / Signalling
What is cond variable?
Thread1 notifies/signals Thread2 for condition. Then thread2 starts
executes, until then thread2 is blocked
Advantages?
1. Avoids busy waiting, ie done by spinlock
2. Similar to [Semaphores]
How condition_variable is implemented internally
| Implemented using | |
|---|---|
| pthread_cond_wait | pthread_cond_t |
| notify_one() |
sys_futex(&cond_sequence, FUTEX_WAKE_PRIVATE, 1) kernel moves one thread from the futex wait-queue to the OS runnable queue. |
| notify_all() |
sys_futex(&cond_sequence, FUTEX_WAKE_PRIVATE, INT_MAX) kernel wakes all threads waiting on that futex address |
Code: Ping Pong
| POSIX(pthread_cond_wait) | C++11 (2 producers 2 consumers) | |
|---|---|---|
| Code |
|
thread1,2 prints ping and then signal on condition variable. thread3,4 waits for signal and then only prints pong notify_all() notify all of threads waiting on condition variable (test).
|
Condition Variable in Rust
bStop: bool = false;
mtx: Mutex<bool> = Mutex::new(false);
cv: Condvar = Condvar::new();
fn foo()
{
// After acquiring lock, data inside mutex can be changed
let mut m = mtx.lock().unwrap();
// Wait until b_enter_f becomes true
while !bStop {
state = cv.wait(m).unwrap();
}
// Do Some work
cv.notify_all();
}
Condition Variable in Golang
sync.Cond. It allows goroutines to wait for a specific condition or
signal other goroutines when that condition changes.
Simple Producer/Consumer Example
package main
import (
"fmt"
"sync"
"time"
)
func main() {
var mu sync.Mutex //mutex
cond := sync.NewCond(&mu) //condition variable
ready := false
go func() { //goroutine that waits for the condition
mu.Lock()
defer mu.Unlock()
for !ready {
fmt.Println("[Consumer] Not ready yet. Waiting...")
cond.Wait() // Suspends execution and releases the lock
}
fmt.Println("[Consumer] Ready signal received! Processing data...")
}()
// Simulate some work before updating the condition
time.Sleep(2 * time.Second)
// Update the condition and signal the waiting goroutine
mu.Lock()
ready = true
fmt.Println("[Producer] Data is ready. Signaling consumer...")
cond.Signal() // Wakes up one waiting goroutine
mu.Unlock()
}