2009-07-14 16 views
-1

ファイルシステムを使用して、アプリケーション全体で永続的なシングルトン(アプリケーションはデータベースを使用しない)を作成します。場合によってはページをロードするのに1〜2分かかることがあり、シングルトンのインスタンスを取得する関数でflockを使用するように問題を絞り込んでいます。 (編集:私のオリジナルのポスト内のコードの最も重要な部分を残し)Windows/NTFSでflockに時折時間がかかるのはなぜですか?

public static final function getInstance() { 
    if (is_null(self::$instance) { 
    $fh = fopen($filename, 'ab+'); 
    if (flock($fh, LOCK_EX)) { 
     $N = filesize($filename); 
     if ($N > 0) { 
     rewind($fh); 
     $s = stream_get_contents($fh); 
     $obj = unserialize($s); 
     } else { 
     $obj = new MyClass(); 
     } 
     self::$instance = $obj; 
     return $obj; 
    } else { 
     fclose($fh); 
     trigger_error("could not create lock", E_USER_WARNING); 
    } 
    } else { 
    return self::$instance; 
    } 
} 

現在XPおよびNTFSを使用して私の開発マシンを実行しているコードここでは、コードの簡易版です。
ロックは常に作成されます(つまり、trigger_errorは呼び出されません)。
遅延はランダムですが、リフレッシュがヒットした場合に発生するように見えます。
群を排除すると、問題は完全に解消されますが、コードが安全でなくなります。

アドバイスはありますか?

誰もがアプリケーション全体の永続シングルトンを作成する良い方法を知っていますか?

答えて

1

if {}句で$ fhをクローズするのは誰ですか?それは開いたままではないのですか?その場合、ロックを解除するのに時間がかかることがあります。 それ以外の場合は、少なくともスクリプトの実行中はハングアップします。

+0

オブジェクトがデストラクタのファイルにシリアル化された後、そのオブジェクトが閉じられた後に閉じられます。 –

+0

これは間違いありません。コードスニペットによれば、ファイル記述子$ fhはgetInstance()内でのみ有効です。ローカル変数であり、グローバルではなく、getInstancde()で "生き残る"別の参照を格納するコードはありません。私。それは、PHPのメソッドのスコープを離れるときに破壊されるはずです。その場合、php_stdiop_close($ fh、...)が呼び出されます。ファイルハンドルを閉じ、このストリームリソースに関連付けられているファイルロックも解放します。本当のコードを見せてくれましたか? – VolkerK

0

LOCK_EXの代わりにLOCK_SHパラメータを使用してロックを試みることができます。後で必要があると判明した場合でも、書き込み用にロックすることはできます。私はできるだけ早くロックを解除するか、他のプロセスが不必要にブロックするでしょう。

関連する問題