MW211 EXIT

devlog
PHP/ファイルの排他制御
2013年02月22日
まず、「flock()」の第二引数は以下の三つ。
・「LOCK_SH」…共有ロック
・「LOCK_EX」…排他ロック
・「LOCK_UN」…アンロック
#Windows版は対象外の「LOCK_NB」については端折ります。

つまり、先日言ってた「funlock()」的なものは
「flock(■,LOCK_UN)」ということになる。

次に話は変わって、ファイルにデータを書き込むタイミング。
「fwrite()」ではなく「fclose()」なんですよこれが。
「fwrite()」は仮のバッファに溜め込むようなもんで、
「fclose()」で初めて日の目を見るわけです。

なので、以下のようにした場合、排他区間は②~④となり、
④~⑤が非排他区間となってしまう。
┌──────────────────────────────────────┐
│$fp = fopen('ouput.txt','w');  …①                                         │
│flock($fp, LOCK_EX);           …②排他                                     │
│fwrite($fp, '出力');           …③排他                                     │
│flock($fp, LOCK_UN);           …④排他                                     │
│fclose($fp);                   …⑤←重要                                   │
└──────────────────────────────────────┘
⑤が終わって初めて遠足、いや排他を終えなきゃならないのに、フライングとなる。

つーことで、「fclose()」でアンロックも兼ねてくれるなら、
自発的にアンロックしちゃダメってのが一昔前の常識だったわけです。
#「fclose()」の中のロック解除の順番はファイル出力の後なんだよねという
  疑問があるかもしれませんが、その辺はちゃんと考慮してくれてるみたいです。
┌──────────────────────────────────────┐
│$fp = fopen('ouput.txt','w');                                               │
│flock($fp, LOCK_EX);                                                        │
│fwrite($fp, '出力');                                                        │
│fclose($fp);                                                                │
└──────────────────────────────────────┘

し・か・し、PHP5.3.2で仕様変更が発生して「fclose()」が
アンロックをやってくれなくなった。
#この原因は、どうやらバグ対応みたい(ファイルを二重に開いた場合とからしい)
  とにかく、クローズに徹して余計なことはしないってことかな

じゃ、どうする?
仕様変更を見なかったことにする?(ロックが解除されません)
手動でアンロックする?(排他が保証されません)

う~ん、身動きがとれない。。。

で、解決策。「fclose()」がやってくれている重要なファイル出力作業を
「fflush()」で先にやっちゃえばいいらしい。
┌──────────────────────────────────────┐
│$fp = fopen('ouput.txt','w');  …①                                         │
│flock($fp, LOCK_EX);           …②排他                                     │
│fwrite($fp, '出力');           …③排他                                     │
│fflush($fp);                       ←重要                                   │
│flock($fp, LOCK_UN);           …④排他                                     │
│fclose($fp);                   …⑤                                         │
└──────────────────────────────────────┘
これなら、排他は保証されるし、排他も解除できる。
分類:PHP