1965 年,Dijkstra 引入信號量解決並發程式設計中的同步與互斥問題。其核心定義:
信號量是一個非負整數,僅支援兩種 原子操作:P (wait) 與 V (signal)
原子操作在執行過程中 不能被中斷。生活類比:
P(sem):
if sem > 0:
sem -= 1
else:
block(current_process) // 掛起進程
語義:申請資源,資源不足則等待
V(sem):
if 有進程等待 sem:
wakeup(one_waiting_process)
else:
sem += 1
語義:釋放資源,喚醒等待者
// 非臨界區
nocritical_code();
P(sem); // 進入臨界區
{
critical_code(); // 共享資源存取
do_something();
}
V(sem); // 離開臨界區
nocritical_code();
初始條件:sem = 1
結果:同一時間僅有一個進程在臨界區 → 實現互斥
| 類型 | 初值 | 用途 | 範例 |
|---|---|---|---|
| 二元信號量 | 1 | 互斥鎖 | 保護共享變數、檔案、硬體裝置 |
| 計數信號量 | N (>0) | 資源計數/同步 | 生產者-消費者緩衝區、連線池 |
| 同步信號量 | 0 | 事件通知 | 執行緒完成通知、非同步 I/O 回調 |
sem_t mutex = 1; // 互斥存取緩衝區
sem_t empty = N; // 空位數量
sem_t full = 0; // 滿位數量
// 生產者
P(empty); P(mutex);
put_item();
V(mutex); V(full);
// 消費者
P(full); P(mutex);
take_item();
V(mutex); V(empty);
理解 P/V 原理後,下一階段將學習:
「信號量是並發程式設計的瑞士刀——簡單強大,但使用不當同樣危險。」