【问题标题】:Best Practice For Sleeping睡眠的最佳实践
【发布时间】:2014-03-02 22:52:37
【问题描述】:

假设您有一个写入文件的进程,并且执行时间正好为 1 秒(理论上)。您在文件上加锁以防止在写入时写入;但是这个问题应该适用于任何比赛条件。最好是“循环检查”还是“等待信号”(如PHP中的pcntl_sigwaitinfo和pcntl_signal)。

如果首选“循环和检查”,为了获得最佳性能,等待接收锁的进程应该休眠多长时间,或者换句话说,进程应该多久唤醒一次以检查锁的状态?

假设 CPU 循环时间为 20 纳秒 (ns):

如果您等待 1 整秒,则浪费的最大时间为 ( 1s - 1ns ) 或几乎一整秒,假设前一个进程在最后一次检查后 1ns 完成。然而,过于频繁地检查也是一种浪费。我正在考虑使用

 [ ( Execution Time / (4 * Execution Time) ]. 

考虑到执行的长度,这个公式应该减少到检查 4 次。大家觉得呢?

【问题讨论】:

  • 如果需要信号量,希望避免 Wait 和 Signal,因为它们在 PHP 中不是跨平台的。
  • 我不是文件系统方面的专家,但这对于 PHP 来说似乎太低级了。
  • 平均执行时间是通过测试而不是实时计算得出的。
  • S.O 的目标是实践,而不是理论
  • 好的,我的过程实际上平均只需要一 (1) 秒。检查前我应该睡多久? (我认为一个公式有助于扩大答案......为什么“理论”是一个既定的标签?)

标签: php multithreading theory


【解决方案1】:

我无法真正理解您正在尝试做的事情,所以我会做出一些假设。

我假设您锁定文件是为了保持内容的完整性,而不是创建某种基于文件的条件,因为您不需要文件来满足条件。

我假设您已经忽略了循环和检查是将竞争条件引入任何事物的好方法这一事实,请考虑以下代码

if (can_lock_file())
    lock_file();

如果多个上下文正在执行,并且我假设这是由于问题上的多线程标记,那么您基本上是在编写死锁 - 如果两个上下文同时调用 can_lock_file,它们都可以获得一个正的返回值,并且都尝试锁定文件,阻塞和/或死锁其中一个上下文,具体取决于代码。

最好的建议是不要在代码中做出这些决定,没有好办法让它正确。

这是一些代码,它有 8 个线程将随机生成的数据写入单个输出文件,该文件的完整性通过互斥锁以适当的方式保存,数据和进程的性质将准确地决定如何使用真正的互斥锁,我猜得最好:

<?php

class FileWriter extends Thread {
    public function __construct($file, $lock) {
        $this->file = $file;
    }

    public function run() {
        /* the file does not need to be locked while data is generated */
        $data = [];
        while (count($data) < 1000) {
            $data[] = md5(mt_rand()*microtime());
        }

        $tid = $this->getThreadId();

        foreach ($data as $line) {
            /* the lock need only be held while the file is written */
            Mutex::lock($this->lock);
            fprintf(
                $this->file,
                "%s#%lu: %s\n", __CLASS__, $tid, $line);
            Mutex::unlock($this->lock);
        }
    }

    protected $file;
    protected $lock;
}


$threads = [];
$thread = 0;

$handle = fopen("test.txt", "w+");
$lock = Mutex::create();

while ($thread<8) {
    $threads[$thread] = new FileWriter($handle, $lock);
    $threads[$thread]->start();
    $thread++;
}

foreach ($threads as $thread)
    $thread->join();


Mutex::destroy($lock);
?>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-15
    • 1970-01-01
    • 2018-10-22
    • 1970-01-01
    • 1970-01-01
    • 2021-12-08
    • 2014-10-08
    相关资源
    最近更新 更多