../../image/benilogo.gifPHP4 について


PHP の flock() について。

 PHPのマニュアル flock() 

ともかく、実際に動かしてみる

  1. flock 排他制御
    num_01 は ループで無駄時間をとる num_02は検証用
    $filename = "num.dat";
    $wait_sec = 5;
    $handle = fopen($filename,'r+');
    set_file_buffer($handle,0);
    flock($handle,LOCK_EX);
    $number = fgets($handle,1024);
    if ($number){
      $number = $number + 1;
    }else{
      $number = 1;
    }
    $finish_time = time() + $wait_sec;
    while($finish_time > time()){
      //無駄ループ
    }
    rewind($handle);
    fputs($handle,$number);
    flock($handle,LOCK_UN);
    
    if (fclose($handle))
       echo "File Close \n";
    echo "約 $wait_sec 秒待つ \n";
    echo "番号=$number \n";
    
    
    $filename = "num.dat";
    $handle = fopen($filename,'r+');
    //  set_file_buffer($handle,0);
    //  flock($handle,LOCK_EX);
      $number = fgets($handle,128);
      if ($number){
        $number = $number + 1;
      }else{
        $number = 1;
      }
      rewind($handle);
      fputs($handle,$number);
    //  flock($handle,LOCK_UN);
    
    if (fclose($handle))
       echo "File Close \n";
    
    echo "番号=$number \n";
    
    
    
     
     最初に 勘違いをしていたのは ロック獲得出来ない場合は
     FALSE を返すのかと思い。
      if ( flock( ){ ・・・・ のように flock( ) の返りを判断しようと
     したのだが
        flock( ) は Default でブロックモードの動作をする。

      ブロックモードでは ロックを獲得出来ない場合は処理が
      止まる。
        つまり、ロックを獲得するまで待っていることになる。
        
      マニュアルには bool flock( ) と書かれているし説明では
      成功した場合に TRUE 、失敗した場合に FALSE を返します。
      と書かれている。 失敗した場合は獲得出来るまで待つ
      のでは?  しかし、そもそも失敗した場合とはどんな場合
      なんだろうか?
      わかった! ブロックモードでないときなのだ!

      次の勘違いは flock するとファイルそのものがロックされる
      と思っていたが、これも間違いのようです。

  2. 検証
    上記ソースの num_01 は ファイルを開いて 数値に +1 してまた、ファイルに戻すのですが flock で while ループを 約 5 秒待たすように
    しています。 num_02 は 同じ処理ですが 無駄ループを無くし、 ロックしないようにしています。
    num_01 を先に起動し、5秒以内に( ロック中) num_02 を 3個別に呼び出すことにすると。
     
    
    1. 最初に @ を呼び出す。
      (これは5秒ロックする。)
    2. その間に A、B、Cを呼び出す。

    結果
    flock( ) を使わないと
    @とAには同一番号272がふられている。

    次に num_02 から flock を活かすようにして同じことを実行してみる。
     上記と同じ要領で実行する。

     こんどは@とAの番号が異なっている
    @は上記と同じ
    A、B、Cは

    $handle = fopen($filename,'r+');
      set_file_buffer($handle,0);
      flock($handle,LOCK_EX);
      $number = fgets($handle,128);
      if ($number){
        $number = $number + 1;
      }else{
        $number = 1;
      }
      rewind($handle);
      fputs($handle,$number);
      flock($handle,LOCK_UN);
    
    if (fclose($handle))
       echo "File Close \n";
    
    echo "番号=$number \n";
    
    

    つまり@が掴んでいる間は排他制御されている
    のでA以降はロックが解除されてから動作する。
    ということのようです。


  3. 勘違いの修正
     flock()で ロック がかかるのではあるが、これはファイルに対してではなく flock( ) そのものがロックである。
    なんか意味不明の文章になっちまったが 最初に思ったのは flock( ) することにより ファイルそのものがロックされるような
    イメージであったのですが( この場合は num.dat にロックがかかるというようなイメージ ) どうもそれは間違いで、flock( ) はそれ自体
    がロックみたいなものなんですね。
    image/flock_03.gif
    • 左図はブロックモードのとき
    • flock( $handle,LOCK_EX | LOCK_NB ) とすると
      ブロックモードでないから他でロックされている場合は
      待たないで FALSE を返します。
    • ともかく ファイル自体がロックされているわけではないので
      ロックされようが、されまいが fgets( ) や fputs( ) によりアクセス
      (読み書き)することは可能です。
    • いわば flock( ) により 旗が立っているみたいなもので
      同じ flock( ) でアクセスする方がその旗を見て処理を決めること
      も出来るようです。

    だいたいこんな感じのようです。 


















目次に戻る

2005/08/07 start ********* Last Update 2006/11/12 18:50 JST

(C) Y.Kondou,2005,2006 All Rights, Reserved.
その他、お気づきの点がありましたら連絡先はこちらから