睡觉的最佳实践

时间:2014-03-02 22:52:38

标签: php multithreading theory

假设您有一个写入文件的进程,并且需要1秒钟(理论值)才能执行。您锁定文件以防止写入时写入;但是这个问题应该适用于任何竞争条件。最好是“循环和检查”或“等待信号”(例如PHP中的pcntl_sigwaitinfo和pcntl_signal)。

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

假设CPU周期时间为20纳秒(ns):

如果等待1秒钟,假设前一个过程在最后一次检查后1ns完成,则最大浪费时间为(1s - 1ns)或几乎整整一秒。但是,经常检查也是浪费。我正在考虑使用

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

在给定执行长度的情况下,此公式应减少检查4次。你们觉得怎么样?

1 个答案:

答案 0 :(得分:0)

我无法理解你正在做什么,确切地说,所以我会做出一些假设。

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

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

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