You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP多线程并发更新文本文件失效问题及解决方案咨询

解决PHP文件并发读写导致found.txt被清空的问题

这个问题我太熟了——文件并发读写冲突确实是PHP处理本地文件时的常见坑,尤其是当多个请求同时操作同一个文件(哪怕是修改不同的条目)时,很容易出现数据覆盖甚至清空的情况。咱们一步步来拆解原因和解决方案:

为什么会出现文件清空的情况?

大概率是你的原有代码没有处理并发锁,并且使用了不安全的文件打开方式。举个例子,如果用file_put_contents($file, $content)直接写入,或者用fopen($file, 'w')打开文件,并发场景下会发生:

  1. 进程A打开文件,用w模式直接截断了文件内容;
  2. 同时进程B也打开了同一个文件,同样截断了内容;
  3. 最后不管哪个进程先写入,都会覆盖掉对方的操作,甚至可能因为文件指针混乱导致最终文件为空。

可靠的解决方案:用文件锁(flock)控制并发

核心思路是给文件加排他锁,同一时间只允许一个进程读写文件,确保操作的原子性。下面是修改后的update.php代码,完全解决并发问题:

<?php
$pokemon = $_GET['pokemon'] ?? '';
if (empty($pokemon)) {
    die('请指定pokemon参数');
}

$file = 'found.txt';

// 打开文件:c+模式保留原有内容,不存在则创建,不会直接截断
$handle = fopen($file, 'c+');
if (!$handle) {
    die('无法打开found.txt文件');
}

// 加排他锁,阻塞等待直到获取锁(避免并发冲突)
if (flock($handle, LOCK_EX)) {
    // 将文件指针移到文件开头,读取全部内容
    fseek($handle, 0);
    $fileContent = fread($handle, filesize($file));
    // 解析现有数据,为空则初始化空数组
    $pokemonData = json_decode($fileContent, true) ?? [];

    // 更新目标pokemon的数值
    $currentValue = isset($pokemonData[$pokemon]) ? $pokemonData[$pokemon] : 0;
    $pokemonData[$pokemon] = $currentValue + 0.0001;

    // 将指针移回开头,截断文件(清除原有内容),写入新数据
    fseek($handle, 0);
    ftruncate($handle, 0);
    fwrite($handle, json_encode($pokemonData, JSON_PRETTY_PRINT));

    // 释放锁
    flock($handle, LOCK_UN);
    echo "更新成功:{$pokemon} 当前数值为 {$pokemonData[$pokemon]}";
} else {
    die('暂时无法获取文件锁,请稍后重试');
}

// 必须关闭文件句柄,确保锁释放
fclose($handle);
?>

关键细节解释

  • c+模式打开文件:这是避免文件被意外清空的核心,它不会像w模式那样打开就截断内容,而是保留原有内容,同时支持读写操作。
  • 排他锁LOCK_EX:同一时间只有一个进程能持有这个锁,其他请求会等待直到锁释放,从根本上避免了并发读写的冲突。
  • 手动控制文件指针和截断:读取内容后,将指针移回开头,截断文件再写入,确保新内容完全覆盖旧内容,不会出现内容拼接的问题。

额外注意事项

  1. 非阻塞锁的可选方案:如果不想让请求等待锁,可以用LOCK_EX | LOCK_NB非阻塞模式,然后添加重试逻辑(比如循环3次尝试获取锁),避免用户直接看到错误。
  2. 文件格式兼容:如果你的found.txt不是JSON格式(比如每行是pokemon:数值),只需要调整读取和解析的逻辑,核心的锁机制保持不变。
  3. 高并发场景建议:如果你的并发请求量很大,长期来看用本地txt文件不是最优解,换成SQLite、MySQL这类数据库会更可靠——数据库本身自带事务和锁机制,能更好地处理并发操作。

内容的提问来源于stack exchange,提问作者Human Khoo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:23:20