解決併發衝突的核心手段是鎖。本文系統整理 PHP 可用的四大鎖機制:文件諮詢鎖、Sync 擴展互斥/讀寫/事件鎖、SysV 信號量、pthreads 互斥鎖,附完整代碼驗證行為差異。
最通用、跨平台。flock($fp, LOCK_EX | LOCK_NB) 非阻塞排他鎖,配合 PID 文件防止重複啟動(如 php-fpm、crontab 任務)。
$fp = fopen('/tmp/process.pid', 'w+');
if (flock($fp, LOCK_EX | LOCK_NB)) {
ftruncate($fp, 0); fwrite($fp, $pid); fflush($fp);
sleep(300); // 長任務
flock($fp, LOCK_UN);
} else { echo "進程已運行"; }
特性: 進程結束自動釋放,支援共享鎖 LOCK_SH 實現讀寫分離。
PECL 安裝 pecl install sync,提供跨進程同步原語。
lock(ms) 超時毫秒,-1 無限等待。readlock/readunlock、writelock/writeunlock 成對使用。wait() 阻塞,fire() 喚醒單一進程(類 Go Cond)。initialval 允許同時進入數。$mutex = new SyncMutex('UniqueName');
$mutex->lock(200); // 200ms 超時
// critical section
$mutex->unlock();
原生 sem_get/acquire/release/remove,需 ftok 產生 key。
$key = ftok(__FILE__, 'c'); $sem = sem_get($key); sem_acquire($sem); // 陣塞 // critical section sem_release($sem);
注意: sem_acquire($sem, true) 非阻塞模式下失敗不自動釋放,release 必須在成功獲取後成對呼叫,否則觸發 Warning。
僅限 ZTS 環境。pthread_mutex_lock/trylock/unlock,trylock 忙碌即刻返回避免死鎖。
pthread_mutex_lock(&cnt.lock); cnt.sum += i; pthread_mutex_unlock(&cnt.lock);
flock (文件) 或 SyncMutexSyncReaderWriterSyncSemaphore / SysV Sempthreads mutex理解各鎖語義與適用邊界,是編寫健壯併發 PHP 程式的關鍵。