【问题标题】:how to synchronise multiple processes in PHP to simulate wait()/notifyAll()PHP中如何同步多个进程来模拟wait()/notifyAll()
【发布时间】:2013-04-17 14:44:31
【问题描述】:

我正在尝试在 PHP 中测试竞争条件。我想让 N 个 PHP 进程准备好做某事,然后阻塞。当我说“开始”时,他们应该同时执行动作。希望这将展示比赛。

在 Java 中,我会使用 Object.wait() 和 Object.notifyAll()。我可以在 PHP 中使用什么?

(可以接受 Windows 或 linux 原生答案)

【问题讨论】:

  • 我会使用文件,并检查file_exists。在这里,它真的取决于“同一时间”的含义。
  • “同一时间”表示并行且所有开始尽可能接近完全相同的时刻。当您说“检查 file_exists”时,您的意思是使用自旋锁吗?这可能行得通。
  • 是的,带有usleep 功能的东西。
  • 如果你使用“usleep”,那就不是spinlock
  • 我已将您的评论写成答案,因为这是我迄今为止最好的答案。随意编写您自己的版本,我会删除我的版本以支持您的版本。

标签: php multithreading process


【解决方案1】:
  • 创建文件“wait.txt
  • 启动N个进程,每个进程的代码如下所示
  • 删除“wait.txt”文件。

...

<?php
while (file_exists('wait.txt')) {}
runRaceTest();

【讨论】:

  • 我喜欢你的回答,但我当然不会拒绝一些额外的声誉:)
【解决方案2】:

通常用PHP文件锁定的方式来使用。创建一个RUN_LOCK 或类似文件并请求file_exists("RUN_LOCK")。该系统还用于保护递归线程中潜在的无限循环。

我决定要求执行该文件。其他方法可能是,文件的存在调用阻塞算法。这取决于你的情况。总是更安全的情况应该更容易实现。

等待代码:

/*prepare the program*/
   /* ... */
/*Block until its time to go*/
define("LOCK_FILE", "RUN_UNLOCK");    //I'd define this in some config.php
while(!file_exists(LOCK_FILE)) {
    usleep(1); //No sleep will eat lots of CPU
}
/*Execute the main code*/
   /* ... */
/*Delete the "run" file, so that no further executions should be allowed*/
usleep(1);  //Just for sure - we want other processes to start execution phase too
if(file_exists(LOCK_FILE))
    unlink(LOCK_FILE);

我想最好有一个阻塞功能,比如这个:

function wait_for_file($filename, $timeout = -1) {
    if($timeout>=0) {
        $start = microtime(true)*1000;    //Remember the start time
    }    
    while(!file_exists($filename)) {      //Check the file existence
        if($timeout>=0) {                 //Only calculate when timeout is set
           if((microtime(true)*1000-$start)>$timeout) //Compare current time with start time (current always will be > than start)
             return false;          //Return failure
        }   
        usleep(1);         //Save some CPU
    }
    return true;           //Return success
}

它实现了超时。您不需要它们,但也许其他人会。
用法:

header("Content-Type: text/plain; charset=utf-8"); 
ob_implicit_flush(true);while (@ob_end_clean());   //Flush buffers so the output will be live stream
define("LOCK_FILE","RUN_FOREST_RUN");  //Define lock file name again
echo "Starting the blocking algorithm. Waiting for file: ".LOCK_FILE."\n"; 
if(wait_for_file(LOCK_FILE, 10000)) {  //Wait for 10 secconds
    echo "File found and deleted!\n";
    if(file_exists(LOCK_FILE))   //May have been deleted by other proceses
        unlink(LOCK_FILE);
}
else {
    echo "Wait failed!\n";
}

这将输出:

Starting the blocking algorithm. Waiting for file: RUN_FOREST_RUN
Wait failed!

~or~

Starting the blocking algorithm. Waiting for file: RUN_FOREST_RUN
File found and deleted!

【讨论】:

  • 谢谢。我认为在等待循环中添加“usleep”会导致线程同步不那么紧密,所以我更喜欢没有它的版本。这种 file_exists 方法不优雅但很有效,就像 PHP 的其余部分一样;-)
  • 一微秒真的是很短的时间间隔。这些线程到底应该做什么?
  • 就我而言,它们旨在参与相当标准的读写竞争条件,如on wikipedia 所示的示例。对于设置测试用例,我们不关心在测试进程中消耗一些 CPU,但我们关心的是让所有进程同时处于“运行”状态。此处调用“usleep”表示该进程对O/S来说是可中断的,并且会分散代码的注意力,所以我认为在这里使用它是不正确的。
  • 当然,测试情况有很大的不同——牺牲一些 CPU 以获得精确的结果是对的。对于其他用户,所需的同步级别可能较低。
【解决方案3】:

PHP 没有多线程。它也没有计划实施。 您可以尝试使用套接字或0MQ 在多个进程之间进行通信

Why does PHP not support multithreading? Php multithread

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-11
    • 2012-10-11
    • 1970-01-01
    • 1970-01-01
    • 2019-02-19
    • 2019-08-21
    • 2012-07-08
    • 1970-01-01
    相关资源
    最近更新 更多