POSIX信號量(<semaphore.h>)是線程同步的核心工具。本文詳細講解四大核心函數的原型、參數、返回值、使用模式及完整示例。
sem_t sem; // 信號量對象,視為不透明類型,僅通過指針操作
sem_init — 初始化
int sem_init(sem_t *sem, int pshared, unsigned int value);
| 參數 | 說明 |
|---|---|
sem | 信號量對象指針 |
pshared | 0:線程間共享(同一進程);非0:進程間共享(需放在共享內存區) |
value | 初始值(可用資源數/信號計數) |
0,失敗返回 -1 並設置 errno。pshared=0。sem_destroy — 銷毀
int sem_destroy(sem_t *sem);
0,失敗返回 -1。sem_wait — P操作 (等待/獲取)
int sem_wait(sem_t *sem);
0,失敗返回 -1(如被信號中斷 EINTR)。sem_post — V操作 (釋放/通知)
int sem_post(sem_t *sem);
sem_wait,喚醒其中一個(通常優先級最高者)。0,失敗返回 -1。
sem_t mutex;
sem_init(&mutex, 0, 1); // 初值1
// 臨界區
sem_wait(&mutex); // 加鎖
// ... 訪問共享資源 ...
sem_post(&mutex); // 解鎖
sem_destroy(&mutex);
#define BUF_SIZE 10
int buffer[BUF_SIZE];
int in=0, out=0;
sem_t empty, full, mutex;
void init() {
sem_init(&empty, 0, BUF_SIZE); // 空槽位數
sem_init(&full, 0, 0); // 滿槽位數
sem_init(&mutex, 0, 1); // 緩衝區互斥
}
void producer(int item) {
sem_wait(&empty); // 等待空槽
sem_wait(&mutex); // 鎖緩衝區
buffer[in] = item;
in = (in+1)%BUF_SIZE;
sem_post(&mutex); // 解鎖
sem_post(&full); // 通知有產品
}
int consumer() {
sem_wait(&full); // 等待產品
sem_wait(&mutex); // 鎖緩衝區
int item = buffer[out];
out = (out+1)%BUF_SIZE;
sem_post(&mutex); // 解鎖
sem_post(&empty); // 通知有空槽
return item;
}
sem_t ready;
sem_init(&ready, 0, 0);
// 線程A:準備數據
prepare_data();
sem_post(&ready); // 通知數據就緒
// 線程B:等待數據
sem_wait(&ready); // 阻塞直到A發信號
use_data();
sem_trywait:非阻塞嘗試獲取,不可用即返回 EAGAIN。sem_timedwait:帶超時等待(絕對時間 struct timespec)。sem_getvalue:獲取當前值(調試用,非同步安全)。
gcc -pthread -o prog prog.c // 必須鏈接 pthread 庫 (包含信號量實現)
sem_init 直接使用 → 未定義行為。pshared 設置錯誤:線程間用非0,進程間用0。sem_post 過多導致信號量溢出(超過 SEM_VALUE_MAX)。POSIX信號量功能強大、語義清晰,是構建生產者消費者、資源池、事件通知等並發模式的利器。熟練掌握 init/wait/post/destroy 四大件,配合互斥量保護共享數據結構,即可駕馭大多數線程同步場景。