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

POSIX 信號量實現線程同步:生產者-消費者模式完整演示

     編輯:關於C語言

POSIX 信號量實現線程同步:生產者-消費者模式完整演示

信號量是經典的線程同步原語,支持計數型同步。本文演示使用 sem_t 實現「寫線程生產數據 → 讀線程消費數據」的嚴格交替同步,對比無同步時的數據競態與亂序。

同步邏輯流程

  1. 主線程 sem_init(&sem, 0, 0) 初始化為 0(無可用數據)。
  2. 讀線程 sem_wait(&sem) P 操作:信號量為 0 時阻塞,等待數據就緒。
  3. 寫線程修改數據後 sem_post(&sem) V 操作:信號量 +1,喚醒讀線程。
  4. 主線程結束前 sem_destroy(&sem) 釋放資源。

關鍵代碼片段

sem_t sem_value;
#define SEM_ENABLE 1

void read_data(char* str) {
    #ifdef SEM_ENABLE
    sem_wait(&sem_value); // P 操作:等待信號
    #endif
    printf("[%s] start reading data\n", str);
    sleep(1); // 模擬讀取耗時
    printf("[%s] data = %d\n", str, data);
    printf("[%s] end reading data\n", str);
}

void write_data(char* str) {
    printf("[%s] start writing data\n", str);
    sleep(1); // 模擬寫入耗時
    data++;
    printf("[%s] data = %d\n", str, data);
    printf("[%s] end writing data\n", str);
    #ifdef SEM_ENABLE
    sem_post(&sem_value); // V 操作:發送信號
    #endif
}

運行結果對比

無同步(數據競態、讀寫亂序)

Thread_1 start reading data
Thread_2 start writing data
Thread_1 data = 0      // 讀到舊值
Thread_1 end reading data
Thread_2 data = 1
Thread_2 end writing data
... 交替混亂 ...

有信號量同步(嚴格寫→讀→寫→讀)

Thread_2 start writing data
Thread_2 data = 1
Thread_2 end writing data
Thread_1 start reading data
Thread_1 data = 1      // 讀到新值
Thread_1 end reading data
Thread_2 start writing data
... 有序交替 ...

關鍵觀察

  • 主線程雖先創建讀線程,但信號量初值 0 導致讀線程阻塞,寫線程先運行,實現「邏輯順序與創建順序解耦」。
  • 信號量計數特性天然支持「多生產者、多消費者」、緩衝區槽位管理(初值 = 緩衝區大小)。
  • sem_wait 原子性保證無競態;sem_post 可在中斷處理程序中調用(異步信號安全)。

工程注意事項

  1. 編譯鏈接需 -lpthread -lrt(Linux)。
  2. 無名信號量(線程間)用 sem_init/sem_destroy;有名信號量(進程間)用 sem_open/sem_close/sem_unlink。
  3. 避免在信號量保護區內調用阻塞系統調用(如 sleep、I/O),防止死鎖或優先級反轉。
  4. 優先考慮條件變量(pthread_cond_t)配合互斥量,語義更清晰(等待條件而非計數)。

總結

信號量以計數器抽象「資源可用數」,實現線程間「等待-通知」同步。本例展示了最基礎的二值信號量(互斥鎖特例)用法,掌握其 P/V 原子操作語義,是多線程編程的必修課。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved