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

PHP 檔案鎖定寫入實作:flock() 併發控制完整範例

     編輯:PHP 綜合知識

多進程/執行緒同時寫入同一檔案會導致資料損毀。PHP flock() 提供諮詢式檔案鎖,配合阻塞等待機制,可安全實現併發寫入。

核心函數封裝

/**
 * 安全寫入檔案(獨佔鎖 + 超時重試)
 * @param string $file_name 檔案路徑
 * @param string $text 寫入內容
 * @param string $mode fopen 模式,預設 'a' 追加
 * @param int $timeout 最大等待秒數
 * @return bool
 */
function file_write($file_name, $text, $mode='a', $timeout=30) {
    $handle = fopen($file_name, $mode);
    if (!$handle) return false;

    // 等待取得獨佔鎖
    while ($timeout > 0) {
        if (flock($handle, LOCK_EX)) break; // 成功取得鎖
        $timeout--;
        sleep(1);
    }

    if ($timeout > 0) {
        fwrite($handle, $text . "\n");
        flock($handle, LOCK_UN); // 釋放鎖
        fclose($handle);
        return true;
    }

    fclose($handle);
    return false; // 超時未取得鎖
}

flock() 操作常數

常數值(舊版)用途
LOCK_SH1共享鎖(讀取)
LOCK_EX2獨佔鎖(寫入)
LOCK_UN3釋放鎖
LOCK_NB4非阻塞模式(配合 LOCK_EX|LOCK_NB)

關鍵注意事項

  1. 諮詢式鎖:僅限協同進程遵守,無法阻止非 flock 的進程讀寫
  2. fclose() 自動釋放:但最佳實踐是顯式 flock($handle, LOCK_UN) 後再 fclose()
  3. 模式選擇:'a' 追加寫入(指標自動移至末尾)、'w' 截斷重寫、'r+' 讀寫不截斷
  4. NFS/網路檔案系統:flock 可能失效,需改用 fcntl 或分散式鎖

讀取時的共享鎖範例

function file_read_locked($file_name) {
    $handle = fopen($file_name, 'r');
    if (!$handle) return false;
    if (flock($handle, LOCK_SH)) {
        $content = stream_get_contents($handle);
        flock($handle, LOCK_UN);
        fclose($handle);
        return $content;
    }
    fclose($handle);
    return false;
}

進階:非阻塞嘗試鎖

if (flock($handle, LOCK_EX | LOCK_NB)) {
    // 立即獲得鎖,執行寫入
    flock($handle, LOCK_UN);
} else {
    // 未獲得鎖,可選擇排隊、丟棄或記錄日誌
}

檔案鎖適合低併發、單機場景(如日誌寫入、簡易計數器)。高併發或分散式環境請改用 Redis SETNX、資料庫行鎖、或專用協調服務。
(ZooKeeper、etcd)

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