條件變數(Condition Variable)配合互斥鎖,是實現執行緒同步、等待/通知機制的核心原語。本文以「執行緒 A 每 3 次通知執行緒 B 執行一次」為例,完整展示 pthread_cond_wait/signal 正確使用模式。
| 函式 | 用途 | 關鍵規則 |
|---|---|---|
pthread_mutex_lock | 鎖定互斥量 | 進入臨界區前必須鎖定 |
pthread_mutex_unlock | 解鎖 | 離開臨界區後解鎖 |
pthread_cond_wait | 等待條件 | 必須在鎖定狀態下呼叫,原子釋放鎖並休眠 |
pthread_cond_signal | 喚醒一個等待執行緒 | 可在鎖內或鎖外呼叫,建議鎖內修改條件後再 signal |
pthread_cond_broadcast | 喚醒所有等待執行緒 | 條件廣播場景 |
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int i = 1; // 共享計數器
void* thread1(void*) { // 生產者:每 3 次通知一次
for (i = 1; i <= 9; ++i) {
pthread_mutex_lock(&mtx);
if (i % 3 == 0)
pthread_cond_signal(&cond); // 條件滿足,通知 thread2
else
printf("thread1: %d\n", i);
pthread_mutex_unlock(&mtx);
printf("Up Unlock\n");
usleep(1500000);
}
return NULL;
}
void* thread2(void*) { // 消費者:等待條件
while (i < 9) {
pthread_mutex_lock(&mtx);
if (i % 3 != 0)
pthread_cond_wait(&cond, &mtx); // 釋放鎖並休眠,被喚醒後重新獲得鎖
printf("thread2: %d\n", i);
pthread_mutex_unlock(&mtx);
printf("Down Unlock\n");
sleep(1);
}
return NULL;
}
int main() {
pthread_t t1, t2;
pthread_create(&t1, NULL, thread1, NULL);
pthread_create(&t2, NULL, thread2, NULL);
pthread_join(t2, NULL); // 等待消費者結束
pthread_mutex_destroy(&mtx);
pthread_cond_destroy(&cond);
return 0;
}
pthread_cond_wait(&cond, &mtx) 原子操作:解鎖 + 進入等待佇列,被喚醒後自動重新鎖定,避免競態while (條件不滿足) pthread_cond_wait(...)signal 可在鎖外呼叫,但「修改條件 → signal」建議在同一個鎖定區間內完成,確保可見性i 必須受 mtx 保護,否則資料競爭#include <mutex>
#include <condition_variable>
#include <thread>
#include <iostream>
std::mutex mtx;
std::condition_variable cv;
int i = 1;
void producer() {
for (i = 1; i <= 9; ++i) {
std::unique_lock lk(mtx);
if (i % 3 == 0) cv.notify_one();
else std::cout << "producer: " << i << '\n';
}
}
void consumer() {
std::unique_lock lk(mtx);
while (i < 9) {
cv.wait(lk, []{ return i % 3 == 0; }); // 謂詞版 wait,自動處理虛假喚醒
std::cout << "consumer: " << i << '\n';
}
}
int main() {
std::thread t1(producer), t2(consumer);
t1.join(); t2.join();
}
pthread_cond_wait 呼叫前未鎖定互斥量 → 未定義行為if 而非 while 檢查條件 → 虛假喚醒導致邏輯錯誤signal 後忘記 unlock → 喚醒的執行緒無法獲得鎖,效能退化