首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

POSIX 執行緒條件變數實戰:互斥鎖與條件變數協同實現執行緒依序啟動

     編輯:關於C語言

前言

條件變數(Condition Variable)配合互斥鎖,是實現執行緒同步、等待/通知機制的核心原語。本文以「執行緒 A 每 3 次通知執行緒 B 執行一次」為例,完整展示 pthread_cond_wait/signal 正確使用模式。

一、核心 API 速查

函式用途關鍵規則
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;
}

三、關鍵細節解析

  1. pthread_cond_wait(&cond, &mtx) 原子操作:解鎖 + 進入等待佇列,被喚醒後自動重新鎖定,避免競態
  2. 條件判斷必須在迴圈中:防止虛假喚醒,模式 while (條件不滿足) pthread_cond_wait(...)
  3. signal 可在鎖外呼叫,但「修改條件 → signal」建議在同一個鎖定區間內完成,確保可見性
  4. 共享變數 i 必須受 mtx 保護,否則資料競爭

四、C++ 封裝風格(RAII)

#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 → 喚醒的執行緒無法獲得鎖,效能退化
  • 條件變數與互斥量未正確初始化/銷毀 → 資源洩漏
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved