信號量是經典的線程同步原語,支持計數型同步。本文演示使用 sem_t 實現「寫線程生產數據 → 讀線程消費數據」的嚴格交替同步,對比無同步時的數據競態與亂序。
sem_init(&sem, 0, 0) 初始化為 0(無可用數據)。sem_wait(&sem) P 操作:信號量為 0 時阻塞,等待數據就緒。sem_post(&sem) V 操作:信號量 +1,喚醒讀線程。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 ... 有序交替 ...
sem_wait 原子性保證無競態;sem_post 可在中斷處理程序中調用(異步信號安全)。-lpthread -lrt(Linux)。sem_init/sem_destroy;有名信號量(進程間)用 sem_open/sem_close/sem_unlink。sleep、I/O),防止死鎖或優先級反轉。pthread_cond_t)配合互斥量,語義更清晰(等待條件而非計數)。信號量以計數器抽象「資源可用數」,實現線程間「等待-通知」同步。本例展示了最基礎的二值信號量(互斥鎖特例)用法,掌握其 P/V 原子操作語義,是多線程編程的必修課。