PHP写入/更新文本文件,如果随机多个线程尝试更新文本文件则不起作用



这是我的文件名代码如果假设我只是使用
更新.php?口袋妖怪=皮卡丘它更新了我发现的皮卡丘值.txt +0.0001

但是现在我的问题,当我有多个线程运行并且随机运行时2 个线程是更新.php?口袋妖怪=皮卡丘和update.php?Pokemon=Zaptos

我看到找到.txt文件是空的比!!所以什么都没有写进去。所以我想当打开 php 文件并将另一个请求发布到服务器时这是一个错误。我该如何解决这个问题,这确实经常出现

找到了.txt

pikachu:2.2122
arktos:0
zaptos:0
lavados:9.2814
blabla:0

更新.php

 <?php
    $file = "found.txt";
    $fh = fopen($file,'r+');
    $gotPokemon = $_GET['pokemon'];
    $users = '';
    while(!feof($fh)) {
        $user = explode(':',fgets($fh));
        $pokename = trim($user[0]);
        $infound = trim($user[1]);
        // check for empty indexes
        if (!empty($pokename)) {
            if ($pokename == $gotPokemon) {
                if ($gotPokemon == "Pikachu"){
                    $infound+=0.0001;
                }
                if ($gotPokemon == "Arktos"){
                    $infound+=0.0001;
                }
                if ($gotPokemon == "Zaptos"){
                    $infound+=0.0001;
                }
                if ($gotPokemon == "Lavados"){
                    $infound+=0.0001;
                }
            }
            $users .= $pokename . ':' . $infound;
            $users .= "rn";
         }
    }
    file_put_contents('found.txt', $users);
    fclose($fh); 
    ?>

我会在打开文件后创建一个独占锁,然后在关闭文件之前释放锁:

要在文件上创建独占锁:

flock($fh, LOCK_EX);

要删除它:

flock($fh, LOCK_UN);

无论如何,您将需要检查其他线程是否已经热锁,因此出现的第一个想法是尝试几次尝试来获取锁,如果最终不可能,则通知用户,抛出异常或任何其他操作以避免无限循环:

$fh = fopen("found.txt", "w+");
$attempts = 0;
do {
    $attempts++;
    if ($attempts > 5) {
        // throw exception or return response with http status code = 500
    }
    if ($attempts != 1) {
        sleep(1);
    }
} while (!flock($fh, LOCK_EX));
// rest of your code
file_put_contents('found.txt', $users);
flock($fh, LOCK_UN); // release the lock
fclose($fh);

更新可能问题仍然存在,因为读取部分,所以让我们在开始阅读之前创建一个共享锁,让我们简化代码:

$file = "found.txt";
$fh = fopen($file,'r+');
$gotPokemon = $_GET['pokemon'];
$users = '';
$wouldblock = true;
// we add a shared lock for reading
$locked = flock($fh, LOCK_SH, $wouldblock); // it will wait if locked ($wouldblock = true)
while(!feof($fh)) {
    // your code inside while loop
}
// we add an exclusive lock for writing
flock($fh, LOCK_EX, $wouldblock);
file_put_contents('found.txt', $users);
flock($fh, LOCK_UN); // release the locks
fclose($fh);

让我们看看它是否有效

最新更新