ファイル ロック
正式名称はアドバイザリーファイルロックで、書籍内で言及されています。 このタイプのロックは比較的一般的です。たとえば、mysql と php-fpm が開始された後、プロセス ID を記録する pid ファイルが作成されます。このファイルはファイル ロックです。
このロックにより、プロセスが繰り返し実行されるのを防ぐことができます。たとえば、crontab を使用する場合、1 つのタスクは 1 分ごとに実行されるように制限されますが、プロセス ロックを解決するために使用されない場合、このプロセスの実行時間は 1 分を超える可能性があります。競合するため、2 つのプロセスを一緒に実行すると問題が発生します。
PID ファイル ロックを使用するもう 1 つの利点は、プロセスが停止信号または再起動信号をそれ自体に送信するのに便利であることです。たとえば、php-fpm を再起動するコマンドは
です。kill -USR2 `cat /usr/local/php/var/run/php-fpm.pid`
pid ファイルに記録されているプロセスに USR2 シグナルを送信します。このシグナルはプロセス通信に属しており、別の章で説明します。
phpのインターフェースはflockであり、ドキュメントは比較的詳細です。まず定義を見てみましょう、 bool flock ( resource $handle , int $operation [, int &$wouldblock ] )。
この関数はデフォルトでブロックしていることに注意してください。ブロックしないようにするには、ビットマスク LOCK_NB を操作に追加します。
リーリーそれを process.php として保存し、php process.php & を実行してから、php process.php を再度実行すると、エラー メッセージが表示されます。 flock には共有ロック LOCK_SH もあります。
ミューテックスロックと読み書きロック
同期モジュールのミューテックス:
Mutex は、相互排除を意味する複合語です。 pecl を使用して同期モジュール (pecl install sync) をインストールします。 ドキュメント内の SyncMutex には、lock と lock の 2 つのメソッドしかありません。コードのテストに直接進みましょう。 IDE で書いたわけではないので、cs は非常に見苦しいですが、無視してください。
mutex.phpとして保存し、php mutex.phpを実行すると、出力は
リーリーここで、サブプロセス 0 と 1 は必ずしも前にあるわけではありません。しかし、ロックを取得できない人が常に存在します。ここでの SyncMutex::lock(int $millisecond) のパラメータはミリ秒で、ブロック期間を表し、-1 は無限ブロックを意味します。
同期モジュールの読み取り/書き込みロック:
SyncReaderWriter のメソッドも同様で、readlock、readunlock、writelock、writeunlock がペアで表示されます。テスト コードは記述されていません。Mutex コードと一致している必要があり、ロックを置き換えるだけです。
同期モジュールのイベント:
golang の Cond に似た感じで、wait() がブロックし、fire() が Event によってブロックされたプロセスを起動します。 Cond を紹介する良い記事があります。Cond がロックの固定的な使用法であることがわかります。 SyncEvent についても同様です。
PHP ドキュメントの例では、fire() メソッドが Web アプリケーションで使用されているようです。
テストコードをアップロードする
リーリーここで意図的に書かれている fire() が 1 つ少ないため、プログラムはブロックされます。これは、 fire() が一度に 1 つのプロセスのみを起動することを証明しています。
pthreadsモジュール
ミューテックスのロックとロック解除:
機能:
リーリー使用法:
スレッドは pthread_mutex_lock() 関数を使用して、指定されたミューテックス変数をロックします。ミューテックスがすでに別のスレッドによってロックされている場合、この呼び出しはミューテックスのロックが解除されるまでスレッドをブロックします。
pthread_mutex_trylock() はミューテックスをロックしようとしますが、ミューテックスがすでにロックされている場合、ルーチンはすぐに「ビジー」エラー コードを返します。このルーチンは pthread_mutex_trylock() で役立つ場合があります。
Q: 同じロックされたミューテックスを待機しているスレッドが複数あります。ミューテックスがロック解除されると、どのスレッドが最初にミューテックスをロックしますか?
A: スレッドが優先スケジューリング メカニズムを使用しない限り、スレッドはシステム スケジューラによって割り当てられ、最初にミューテックスをロックするスレッドはランダムです。
リーリー
セマフォ
同期モジュールのセマフォ:
SyncSemaphore ドキュメントには、それと Mutex の違いは、セマフォは一度に複数のプロセス (またはスレッド) によって取得できるのに対し、ミューテックスは一度に 1 つしか取得できないことであることが示されています。そのため、SyncSemaphore のコンストラクターには、セマフォを何プロセスで取得できるかを指定するパラメーターがあります。
public SyncSemaphore::__construct ([ string $name [, integer $initialval [, bool $autounlock ]]] ) は、この $initialval (初期値) です
リーリー
$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 \n"; }else{ echo "child process {$i} is born. \n"; obtainLock($sem, $i); } } while (pcntl_waitpid(0, $status) != -1) { $status = pcntl_wexitstatus($status); echo "Child $status completed\n"; } sem_remove($sem); // finally remove the sem function obtainLock ($sem, $i){ echo "process {$i} is getting the sem \n"; $res = sem_acquire($sem, true); sleep(1); if (!$res){ echo "process {$i} unable to get sem. \n"; }else{ echo "process {$i} successfully got the sem \n"; sem_release($sem); } exit(); }
这里有一个问题,sem_acquire()第二个参数$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的文件, 一般使用项目中的文件,第二个是单字符字符串。返回一个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