ZetCode

PHP flock 函数

最后修改于 2025 年 4 月 3 日

PHP flock 函数提供咨询性文件锁定。它有助于防止多个进程访问同一文件时发生竞态条件。

基本定义

flock 函数允许您获取或释放对已打开文件的锁定。它作用于文件指针资源,并支持共享/独占锁定。

语法:flock(resource $stream, int $operation, int &$would_block = null): bool。该函数成功时返回 true,失败时返回 false。

基本独占锁定示例

此示例展示了如何获取独占锁定以写入文件。

basic_exclusive_lock.php
<?php

declare(strict_types=1);

$file = fopen("data.txt", "c+");

if (flock($file, LOCK_EX)) {
    fwrite($file, "Writing with exclusive lock\n");
    flock($file, LOCK_UN); // Release lock
} else {
    echo "Couldn't get the lock!";
}

fclose($file);

此示例在写入前获取独占锁定 (LOCK_EX)。使用 LOCK_UN 释放锁定。一次只能有一个进程持有独占锁定。

共享锁定示例

此示例演示了使用共享锁定来安全地读取文件。

shared_lock.php
<?php

declare(strict_types=1);

$file = fopen("data.txt", "r");

if (flock($file, LOCK_SH)) {
    $content = fread($file, filesize("data.txt"));
    echo $content;
    flock($file, LOCK_UN);
} else {
    echo "Couldn't get the shared lock!";
}

fclose($file);

多个进程可以同时持有共享锁定 (LOCK_SH)。当您希望允许多个并发读取但防止在读取期间进行写入时,这很有用。

非阻塞锁定示例

此示例展示了如何尝试非阻塞锁定,如果不可用则立即失败。

non_blocking.php
<?php

declare(strict_types=1);

$file = fopen("data.txt", "c+");

if (flock($file, LOCK_EX | LOCK_NB, $would_block)) {
    if ($would_block) {
        echo "Lock is held by another process\n";
    }
    fwrite($file, "Non-blocking write\n");
    flock($file, LOCK_UN);
} else {
    echo "Couldn't get non-blocking lock!\n";
}

fclose($file);

LOCK_NB 标志使函数在无法获取锁定后立即返回。 $would_block 参数指示锁定是否因争用而失败。

带超时的文件锁定

此示例实现了获取锁定的简单超时机制。

lock_timeout.php
<?php

declare(strict_types=1);

function acquireLockWithTimeout($file, int $timeout = 5): bool {
    $start = time();
    
    while (!flock($file, LOCK_EX | LOCK_NB)) {
        if (time() - $start >= $timeout) {
            return false;
        }
        usleep(100000); // Wait 100ms before retry
    }
    
    return true;
}

$file = fopen("data.txt", "c+");

if (acquireLockWithTimeout($file)) {
    fwrite($file, "Write with timeout lock\n");
    flock($file, LOCK_UN);
} else {
    echo "Failed to acquire lock within timeout\n";
}

fclose($file);

此示例通过反复尝试获取非阻塞锁定来实现自定义超时。它等待最多 5 秒后放弃。

进程同步示例

此示例演示了使用文件锁定进行进程间同步。

process_sync.php
<?php

declare(strict_types=1);

$lockFile = fopen("process.lock", "c+");

if (!flock($lockFile, LOCK_EX)) {
    die("Could not acquire lock\n");
}

// Critical section
file_put_contents("output.log", "Process " . getmypid() . " running\n", FILE_APPEND);
sleep(2); // Simulate work

flock($lockFile, LOCK_UN);
fclose($lockFile);

echo "Process completed\n";

这确保了脚本一次只运行一个实例。锁定文件充当进程同步的互斥锁。

最佳实践

来源

PHP flock 文档

本教程涵盖了 PHP flock 函数,并提供了实际示例,展示了用于安全文件操作的文件锁定技术。

作者

我叫 Jan Bodnar,是一名充满热情的程序员,拥有丰富的编程经验。自 2007 年以来,我一直在撰写编程文章。迄今为止,我已撰写了 1400 多篇文章和 8 本电子书。我在编程教学方面拥有十多年的经验。

列出 所有 PHP 文件系统函数