Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【PHP8.x】LOCK_NB定数の使い方

LOCK_NB定数の使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

LOCK_NB定数は、PHPのファイルシステム操作、特にファイルロックの際にノンブロッキング動作を指定するために使用される定数です。ファイルロックとは、複数のプログラムが同時に一つのファイルにアクセスする際に、データの一貫性を保つために、一時的にそのファイルへのアクセスを制御する仕組みのことです。

通常、ファイルロックを行う際、もし他のプログラムが既にそのファイルをロックしている場合、現在のプログラムはロックが解除されるまで処理を一時停止(ブロック)します。しかし、LOCK_NB定数を指定すると、ロックがすぐに取得できない場合でも、プログラムは待機せず、直ちに処理を続行します。このとき、ロックを試みた関数(例えばflock()関数)は、ロックが取得できなかったことを示す値(通常はfalse)を返します。

この機能により、プログラムはロックが取得できない場合でも、システムの応答性を損なうことなく、他の処理を実行したり、後でロックを再試行するなどの柔軟な対応が可能になります。例えば、ウェブサーバーのように多くのリクエストを同時に処理する環境で、ファイルアクセスによるアプリケーション全体の停止を防ぐために非常に有効です。LOCK_NBは、共有ロックを示すLOCK_SHや、排他ロックを示すLOCK_EXといった他のロックモードと組み合わせて使用されることが一般的です。

構文(syntax)

1flock($filePointer, LOCK_EX | LOCK_NB);

引数(parameters)

引数なし

引数はありません

戻り値(return)

戻り値なし

戻り値はありません

サンプルコード

PHP flock LOCK_NB で非ブロッキングロックを試行する

1<?php
2
3/**
4 * flock() 関数と LOCK_NB 定数を使用して、ファイルの非ブロッキングロックを試行するサンプルコード。
5 *
6 * LOCK_NB (Non-Blocking) 定数は、flock() 関数がロックを取得できなかった場合に
7 * 待機せずに即座に false を返すように指示します。
8 * これにより、アプリケーションはロックが取得できるまでブロックされることなく、
9 * 他の処理を続行したり、後でロックを再試行したりできます。
10 */
11
12// ロックを試行する一時ファイルの名前を定義します。
13$lockFileName = 'app_process.lock';
14
15// ファイルを書き込みモードで開きます。ファイルが存在しない場合は作成されます。
16// 'w+' モードは読み書きを可能にし、ファイルポインタを先頭に設定します。
17// flock() は有効なファイルハンドルを必要とします。
18$fileHandle = @fopen($lockFileName, 'w+');
19
20if (!$fileHandle) {
21    // ファイルを開くのに失敗した場合のエラー処理。
22    echo "エラー: ロックファイル '{$lockFileName}' を開けませんでした。\n";
23    exit(1);
24}
25
26echo "ロックファイル '{$lockFileName}' を開きました。\n";
27
28// 排他ロック (LOCK_EX) を非ブロッキングモード (LOCK_NB) で試行します。
29// LOCK_EX | LOCK_NB のようにビットOR演算子 (|) を使って複数のフラグを組み合わせます。
30if (flock($fileHandle, LOCK_EX | LOCK_NB)) {
31    // ロックの取得に成功した場合。
32    echo "非ブロッキングモードで排他ロックを取得しました。\n";
33    echo "このロックは " . getmypid() . " プロセスによって保持されています。\n";
34    echo "数秒間、重要な処理をシミュレートします...\n";
35
36    // ロックを保持している間に、ここにアプリケーションの主要なロジックを配置します。
37    // 例として、2秒間待機します。
38    sleep(2);
39
40    echo "重要な処理が完了しました。\n";
41
42    // 明示的にロックを解放します。ファイルハンドルを閉じると自動的に解放されますが、
43    // 明示することでコードの意図が明確になります。
44    flock($fileHandle, LOCK_UN);
45    echo "ロックを解放しました。\n";
46
47} else {
48    // ロックの取得に失敗した場合。
49    // これは、他のプロセスがすでにこのファイルをロックしている可能性があることを意味します。
50    echo "非ブロッキングモードで排他ロックを取得できませんでした。別のプロセスがすでに動作している可能性があります。\n";
51}
52
53// ファイルハンドルを閉じます。これにより、まだ解放されていなければロックも解放されます。
54fclose($fileHandle);
55echo "ファイルハンドルを閉じました。\n";
56
57// ロックファイルは通常、アプリケーション終了時に削除されます(または次回の実行で上書きされます)。
58// ここでは、サンプルコードのクリーンアップとして削除します。
59if (file_exists($lockFileName)) {
60    unlink($lockFileName);
61    echo "ロックファイル '{$lockFileName}' を削除しました。\n";
62}
63
64?>

このPHPサンプルコードは、flock()関数とLOCK_NB定数を用いて、ファイルの非ブロッキングロックを試行する方法を示しています。LOCK_NB定数は「Non-Blocking(非ブロッキング)」を意味し、flock()関数がファイルのロックを試みた際に、もしロックがすぐに利用できない場合でも、待機せずに即座に失敗(false)を返すように指示します。これにより、プログラムがロックの取得で停止することなく、他の処理を続けたり、後でロックを再試行したりできます。

コードではまず、一時ファイルを開き、そのファイルハンドルを取得します。次に、flock($fileHandle, LOCK_EX | LOCK_NB)という形で、排他ロック(LOCK_EX)を非ブロッキングモード(LOCK_NB)で取得しようとします。ここで|演算子は、複数のフラグ(動作モード)を組み合わせるために使用されます。flock()関数は、ロックの取得に成功すればtrueを、失敗すればfalseを戻り値として返します。

ロックの取得に成功した場合、コードは重要な処理をシミュレートした後、flock($fileHandle, LOCK_UN)を使ってロックを明示的に解放します。もしロックの取得に失敗した場合は、その旨を通知し、他のプロセスがすでにロックを保持している可能性を示します。最後に、ファイルハンドルを閉じ、使用したロックファイルを削除してクリーンアップします。

LOCK_NB定数は、flock()関数でファイルのロックを試みた際に、ロックが取得できなかった場合でもプログラムが待機せずに即座に制御を返す「非ブロッキングモード」を指定します。これにより、アプリケーションはロック取得を待つことなく他の処理を続行できます。通常は、LOCK_EX | LOCK_NBのようにビットOR演算子を用いて、排他ロック(LOCK_EX)などのロックタイプと組み合わせて使用します。fopen()でファイルハンドルを確実に取得し、flock()の戻り値(trueまたはfalse)に応じて適切なエラー処理や代替処理を実装することが重要です。ロックは、flock($fileHandle, LOCK_UN)で明示的に解放するか、fclose()でファイルハンドルを閉じると自動的に解放されます。ロックファイルの作成から使用後の削除まで、そのライフサイクル全体を適切に管理してください。

関連コンテンツ