PHP写入/更新文本文件,如果随机多线程尝试更新文本文件

时间:2018-03-19 16:50:57

标签: php python multithreading file text

这是我的带文件名的代码 如果我只是说使用
它,它确实可以正常工作 update.php?口袋妖怪皮卡丘= 它更新了我的found.txt +0.0001

中的皮卡丘值

但现在我的问题,当我有多个线程运行并随机 2个线程 update.php?口袋妖怪皮卡丘= 和 update.php?小宠物= zaptos

我看到了found.txt文件 是空的!! 所以没有任何东西写在那里了。 所以我猜它是一个错误,当PHP文件打开,另一个请求发布到服务器。 我怎么能解决这个问题呢?

found.txt

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

update.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 .= "\r\n";
         }
    }

    file_put_contents('found.txt', $users);

    fclose($fh); 
    ?>

1 个答案:

答案 0 :(得分:0)

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

用于创建对文件的独占锁定:

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);

让我们看看它是否有效