PHPプログラミングにおけるロック
PHPプログラミングにおけるロック
最近『Linuxプロセスを理解する』というオープンソースの本を読んで、リンクしました.この本はlinuxの中のプロセスの概念を説明して、ロックとプロセス間の通信(IPC)に対していくつか総括があります.しかし、この本の記述言語はgolangで、普段はあまり使われていないので、概念に対応してphpのインタフェースを探したいと思っています.
ファイルロック
フルネームは
このロックは、crontabを使用する場合など、プロセスを繰り返し実行することを防止します.たとえば、1分ごとにタスクを実行することを制限しますが、このプロセスの実行時間は1分を超える可能性があります.プロセスロックを使用しないで競合を解決すると、2つのプロセスが一緒に実行されると問題が発生します.
PIDファイルロックを使用すると、プロセスが自分に停止または再起動信号を送るのを容易にするメリットがあります.例えばphp-fpmを再起動するコマンドは
phpのインタフェースは
なお、この関数のデフォルトはブロックであり、operationにbitmask
反発ロックと読み書きロック
syncモジュール内のMutex
Mutexは組み合わせ語で、mutual exclusionです.peclでsyncモジュール、
ここでサブプロセス0と1は必ずしも誰が前にいるとは限らない.しかし、いつも鍵がかかっていないものがあります.ここで
syncモジュールの読み書きロック
syncモジュールのEvent
感覚はgolangの
テストコード
ここではわざとfire()を1つ少なく書くので、プログラムがブロックされ、fire()が一度に1つのプロセスだけを呼び覚ますことを証明します.
pthreadsモジュール
Mutex、Cond、Poolも見たようです.見る暇がなくて、見終わってから補充します.
しんごうりょう
syncモジュールにおける信号量
このとき、両方のプロセスがロックされます.
Sysvsemモジュールにおける信号量 を作成する. の取得を要求する.
ここで問題があります.
また、
出力は
最後に、もし文の中に間違いがあったら、大神に指摘してもらいたい.菜鳥の進歩を助けてください.ありがとうございました.
最近『Linuxプロセスを理解する』というオープンソースの本を読んで、リンクしました.この本はlinuxの中のプロセスの概念を説明して、ロックとプロセス間の通信(IPC)に対していくつか総括があります.しかし、この本の記述言語はgolangで、普段はあまり使われていないので、概念に対応してphpのインタフェースを探したいと思っています.
ファイルロック
フルネームは
advisory file lock
で、本には言及されています.このようなロックは、mysql、php-fpmが起動するとpidファイルにプロセスidが記録されます.このファイルがファイルロックです.このロックは、crontabを使用する場合など、プロセスを繰り返し実行することを防止します.たとえば、1分ごとにタスクを実行することを制限しますが、このプロセスの実行時間は1分を超える可能性があります.プロセスロックを使用しないで競合を解決すると、2つのプロセスが一緒に実行されると問題が発生します.
PIDファイルロックを使用すると、プロセスが自分に停止または再起動信号を送るのを容易にするメリットがあります.例えばphp-fpmを再起動するコマンドは
kill -USR2 `cat /usr/local/php/var/run/php-fpm.pid`
USR2
信号をpidファイルに記録するプロセスに送信し、信号はプロセス通信に属し、別のページを開く.phpのインタフェースは
flock
で、ドキュメントは比較的詳細です.定義を見てみましょうbool flock ( resource $handle , int $operation [, int &$wouldblock ] )
はファイルシステムポインタであり、典型的にはfopen()によって作成されるresource(リソース)である.これはflockを使用してファイルを開く必要があることを意味します.$handle
は動作タイプである.$operation
ロックがブロックする場合、この変数は1に設定される.なお、この関数のデフォルトはブロックであり、operationにbitmask
&$wouldblock
を追加しなければならない.次にテストします.$pid_file = "/tmp/process.pid";
$pid = posix_getpid();
$fp = fopen($pid_file, 'w+');
if(flock($fp, LOCK_EX | LOCK_NB)){
echo "got the lock
";
ftruncate($fp, 0); // truncate file
fwrite($fp, $pid);
fflush($fp); // flush output before releasing the lock
sleep(300); // long running process
flock($fp, LOCK_UN); //
} else {
echo "Cannot get pid lock. The process is already up
";
}
fclose($fp);
LOCK_NB
として保存し、process.php
を実行します.この場合、php process.php &
を再度実行すると、エラーメッセージが表示されます.flockにも共有ロックがある、php process.php
.反発ロックと読み書きロック
syncモジュール内のMutex
Mutexは組み合わせ語で、mutual exclusionです.peclでsyncモジュール、
LOCK_SH
をインストールします.ドキュメントのSyncMutexには2つの方法しかありません.lockとunlock、コードテストに直接行きましょう.IDEで書かれていないので、csは異常に醜いので、無視してください.$mutex = new SyncMutex("UniqueName");
for($i=0; $i<2; $i++){
$pid = pcntl_fork();
if($pid <0){
die("fork failed");
}elseif ($pid>0){
echo "parent process
";
}else{
echo "child process {$i} is born.
";
obtainLock($mutex, $i);
}
}
while (pcntl_waitpid(0, $status) != -1) {
$status = pcntl_wexitstatus($status);
echo "Child $status completed
";
}
function obtainLock ($mutex, $i){
echo "process {$i} is getting the mutex
";
$res = $mutex->lock(200);
sleep(1);
if (!$res){
echo "process {$i} unable to lock mutex.
";
}else{
echo "process {$i} successfully got the mutex
";
$mutex->unlock();
}
exit();
}
pecl install sync
、run mutex.php
、output isとして保存parent process
parent process
child process 1 is born.
process 1 is getting the mutex
child process 0 is born.
process 0 is getting the mutex
process 1 successfully got the mutex
Child 0 completed
process 0 unable to lock mutex.
Child 0 completed
ここでサブプロセス0と1は必ずしも誰が前にいるとは限らない.しかし、いつも鍵がかかっていないものがあります.ここで
php mutex.php
のパラメータはmillisecondであり、ブロックの時間長を表し、-1は無限ブロックである.syncモジュールの読み書きロック
SyncMutex::lock(int $millisecond)
の方法は似ていて、SyncReaderWriter
、readlock
、readunlock
、writelock
、writeunlock
、ペアで現れてもいいです.テストコードを書いていません.Mutexのコードと一致するはずです.ロックを交換すればいいです.syncモジュールのEvent
感覚はgolangの
Cond
と比較して、wait()
が閉塞し、fire()
がEvent閉塞のプロセスを呼び覚ます.Cond
を紹介した良い文があり、Cond
が鍵の固定的な使い方であることがわかります.SyncEvent
も同じです.phpドキュメントの例によると、fire()メソッドはwebアプリケーションで使用できるようです.テストコード
for($i=0; $i<3; $i++){
$pid = pcntl_fork();
if($pid <0){
die("fork failed");
}elseif ($pid>0){
//echo "parent process
";
}else{
echo "child process {$i} is born.
";
switch ($i) {
case 0:
wait();
break;
case 1:
wait();
break;
case 2:
sleep(1);
fire();
break;
}
}
}
while (pcntl_waitpid(0, $status) != -1) {
$status = pcntl_wexitstatus($status);
echo "Child $status completed
";
}
function wait(){
$event = new SyncEvent("UniqueName");
echo "before waiting.
";
$event->wait();
echo "after waiting.
";
exit();
}
function fire(){
$event = new SyncEvent("UniqueName");
$event->fire();
exit();
}
ここではわざとfire()を1つ少なく書くので、プログラムがブロックされ、fire()が一度に1つのプロセスだけを呼び覚ますことを証明します.
pthreadsモジュール
Mutex、Cond、Poolも見たようです.見る暇がなくて、見終わってから補充します.
しんごうりょう
syncモジュールにおける信号量
SyncSemaphore
文書には、Semaphoreは一度に複数のプロセス(またはスレッド)によって得られるが、Mutexは一度に1つしか得られない点で、Mutexとは異なる点が示されている.したがって、SyncSemaphore
の構造関数では、信号量がどのくらいのプロセスで得られるかを指定するパラメータがある.public SyncSemaphore::__construct ([ string $name [, integer $initialval [, bool $autounlock ]]] )
はこの$initialval
(initial value)です$lock = new SyncSemaphore("UniqueName", 2);
for($i=0; $i<2; $i++){
$pid = pcntl_fork();
if($pid <0){
die("fork failed");
}elseif ($pid>0){
echo "parent process
";
}else{
echo "child process {$i} is born.
";
obtainLock($lock, $i);
}
}
while (pcntl_waitpid(0, $status) != -1) {
$status = pcntl_wexitstatus($status);
echo "Child $status completed
";
}
function obtainLock ($lock, $i){
echo "process {$i} is getting the lock
";
$res = $lock->lock(200);
sleep(1);
if (!$res){
echo "process {$i} unable to lock lock.
";
}else{
echo "process {$i} successfully got the lock
";
$lock->unlock();
}
exit();
}
このとき、両方のプロセスがロックされます.
Sysvsemモジュールにおける信号量
sem_get
信号量sem_remove
削除信号量(一般的には使用しない)sem_acquire
信号量sem_release
信号量を解放する.sem_acquire
とペアで使用します.$key = ftok('/tmp', 'c');
$sem = sem_get($key);
for($i=0; $i<2; $i++){
$pid = pcntl_fork();
if($pid <0){
die("fork failed");
}elseif ($pid>0){
//echo "parent process
";
}else{
echo "child process {$i} is born.
";
obtainLock($sem, $i);
}
}
while (pcntl_waitpid(0, $status) != -1) {
$status = pcntl_wexitstatus($status);
echo "Child $status completed
";
}
sem_remove($sem); // finally remove the sem
function obtainLock ($sem, $i){
echo "process {$i} is getting the sem
";
$res = sem_acquire($sem, true);
sleep(1);
if (!$res){
echo "process {$i} unable to get sem.
";
}else{
echo "process {$i} successfully got the sem
";
sem_release($sem);
}
exit();
}
ここで問題があります.
sem_acquire()
の2番目のパラメータ$nowaitのデフォルトはfalseで、ブロックされています.trueとして、ロックが失敗した場合、後のsem_release
はPHP Warning: sem_release(): SysV semaphore 4 (key 0x63000081) is not currently acquired in /home/jason/sysvsem.php on line 33
に警告するので、ここでのrelease操作はロックを取得した場合に実行しなければならない.前のいくつかの例ではこの問題はなく、ロックを取得していなくてもreleaseを実行してもエラーは報告されない.もちろんペアで現れ、ロックが得られた場合にreleaseするのが望ましい.また、
ftok
という方法のパラメータは、最初はexisting、accessableのファイルでなければならず、一般的にプロジェクトのファイルを使用し、2番目は単一文字文字文字列である必要があることを説明する必要があります.intを返します.出力は
parent process
parent process
child process 1 is born.
process 1 is getting the mutex
child process 0 is born.
process 0 is getting the mutex
process 1 successfully got the mutex
Child 0 completed
process 0 unable to lock mutex.
Child 0 completed
最後に、もし文の中に間違いがあったら、大神に指摘してもらいたい.菜鳥の進歩を助けてください.ありがとうございました.