PHPプロセスロック問題の分析と研究

WBOY
リリース: 2016-06-13 12:20:46
オリジナル
1420 人が閲覧しました

1. 読み取りロックと書き込みロックを区別します。
毎回書き込みロックを使用すると、ファイルを読み取るために複数のプロセスがキューに入る必要があり、明らかに効率的ではありません。
2. ブロッキング モードと非ブロッキング モードを区別します。
一般に、1 つのプロセスがファイルを書き込んでいる場合は、他のプロセスをブロックする必要があります。ただし、多くの場合、最初に別の処理を行ってから、他のプロセスがファイルを書き込んでいるかどうかを判断できます。存在しない場合は、データを追加する方が効率的です。
3. Linux でのファイルのロックのバグ、特に gfs ファイル システムのバグを修正しました。
コードは次のとおりです:

コードをコピーします コードは次のとおりです:

class File_Lock
{
private $name;
private $mode;
function __construct($filename, $mode = 'a b')
🎜>global $php_errormsg;
$this->name = $filename;
$path = dirname($this->name);
if ($path == '.' || ! is_dir($path)) {
global $config_file_lock_path;
$this->name = str_replace(array("/", "\"), array("_", "_"), $this ->name);
if ($config_file_lock_path == null) {
$this->name = dirname(__FILE__) . else {
$ this->name = $config_file_lock_path . $this->name;
$this->mode = $mode; $this->handle = @fopen($this->name, $mode);
if ($this->handle == false) {
throw new Exception($php_errormsg); >}
}
public function close()
{
if ($this->handle !== null ) {
@fclose($this->handle); 🎜>$this->handle = null;
}
}
パブリック関数 __destruct()
{
$this->close()
public function lock($lockType , $nonBlockingLock = false)
{
if ($nonBlockingLock) {
return flock($this->handle, $lockType | LOCK_NB);
};
return flock( $this->handle, $lockType);
}
}
public function readLock()
{
return $this->lock(LOCK_SH) ;
}
パブリック関数 writeLock($wait = 0.1)
{
$startTime = microtime(true);
do {
$canWrite; = flock($this- >handle, LOCK_EX);
if(!$canWrite) {
usleep(rand(10, 1000)); while ((!$canWrite) ) && ((microtime( true) - $startTime) < $wait));
}
/**
* マルチスレッドシステムで番号を記録したくない場合は、
* ロックを開いて、MOD を使用してください。ファイルを fopen しても
* データは破壊されません。
*
* この関数はデルト値をインクリメントし、ファイルに保存します。
*
* @param int $delt
* @return int
*/
パブリック関数 increment($delt = 1)
{
$n = $this->get();
$this->set($n);
return $n; 🎜>パブリック関数 get( )
{
fseek($this->handle, 0)
return (int)fgets($this->handle);
public function set($value )
{
ftruncate($this->handle, 0);
return fwrite($this->handle, (string)$value);
パブリック関数unlock ()
{
if ($this->handle !== null ) {
return flock($this->handle,
} else; {
return true ;
}
}
}
?>


テストコード:



code

コードは次のとおりです。


/**
* 書き込みロックテストを実行します
* スレッド 1 を開きます
*/
require("file_lock.php"); 🎜>$lock = new File_Lock(dirname (dirname(__FILE__)) . "/FileLock.lock");
/**単一スレッドのロック速度は 1 秒あたり 30,000 回です。 **/
/**2 つのスレッドで 20,000 データを書き込み、約 7 秒かかります*/

/ **1 スレッドで 10,000 データを書き込むのにかかる時間は約 3.9 秒です。実際には 2 つのファイルが同時に書き込まれるため、より高速になります。*/
/**ロックしない場合、プロセスの書き込みには約 2.8 秒かかります。ロックには代償が伴います。*/
/**ロックがないと、2 つのプロセスの分散はあまり均等ではなくなり、ほとんどのプロセスが競合します。*/

$lock->writeLock(); (); $lock->unlock(); while ($lock->get() < 2) { usleep(1000)>} 1);

エコー "n の実行を開始";

$t1 = microtime(true);
for ($i = 0; $i <10000; $i ); >$lock->writeLock() ;
$lock->unlock();
}
$t2 (true) - $t1;
echo $t2 ;
?>


単純なスレッド同期を実現し、2 つのプロセスが同時に実行できるようにします。もちろん、これには一定の誤差があります
ここでの誤差は 0.001 秒です。
前の memcache メッセージ キューでこのクラスを使用するだけで、スレッドセーフなメッセージ キューを実装できます。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のおすすめ
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート