PHP中檔案鎖
阿新 • • 發佈:2021-09-05
PHP中檔案鎖
檔案鎖的用途:
若一個人在寫入一個檔案,另外一個人同時也打個了這個檔案進行寫入檔案。
這情況下,如果遇到一定的碰撞概率的話,不知道到底誰的操作為準。
因此,這個時候我們引入鎖機制。
若使用者A在寫入或者讀取這個檔案的時候,將檔案加上共享鎖。我可以讀,其他人也可以讀。
但是,我如果這與的時候。我使用獨佔鎖。這個檔案歸我了,你們都別動,除非我將檔案鎖進行釋放。
注意:加上了檔案鎖後要注意釋放。
一、交叉寫入
1、檔案沒有加鎖
demo.php
header('content-type:text/html;charset=utf-8'); $filename = 'flock.txt'; $handle = fopen($filename,'a'); for($i=0;$i<1000000; $i++){ fwrite($handle,'x'); }
demo_b.php
header('content-type:text/html;charset=utf-8');
$filename = 'flock.txt';
$handle = fopen($filename,'a');
for($i=0;$i<1000000; $i++){
fwrite($handle,'b');
}
2、新增獨佔鎖
demo.php
header('content-type:text/html;charset=utf-8'); $filename = 'flock.txt'; $handle = fopen($filename,'a'); flock($handle,LOCK_EX); for($i=0;$i<1000000; $i++){ fwrite($handle,'x'); }
demo_b.php
header('content-type:text/html;charset=utf-8');
$filename = 'flock.txt';
$handle = fopen($filename,'a');
flock($handle,LOCK_EX);
for($i=0;$i<1000000; $i++){
fwrite($handle,'b');
}
二、關於阻塞
在PHP 5.3.2版本之前,鎖會被 fclose() 釋放(在指令碼結束後會自動呼叫),現在需要手動解鎖
鎖方式 | 說明 |
---|---|
LOCK_SH | 取得共享鎖(讀取的程式) |
LOCK_EX | 取得獨佔鎖(寫入的程式) |
LOCK_UN | 釋放鎖定 (無論共享或獨佔) |
LOCK_NB | 在flock()鎖定時不阻塞 windows不支援 |
例項1:A使用獨佔鎖寫檔案,B讀取檔案,阻塞
a.php
$file = 'test.txt';
$fp = fopen($file, 'w');
if(flock($fp, LOCK_EX)){ // 取得獨佔鎖
fwrite($fp, "Hello World\r\n"); // 寫入資料
sleep(10); // sleep 10秒,檔案被鎖定
fwrite($fp, "Hello PHP\r\n"); // 寫入資料
flock($fp, LOCK_UN); // 解鎖
}
fclose($fp);
b.php
$file = 'test.txt';
$fp = fopen($file, 'r');
if(flock($fp, LOCK_SH)){ // 取得共享鎖
while(!feof($fp)){
echo fread($fp, 100);
}
flock($fp, LOCK_UN);
}
fclose($fp);
先執行a.php,然後執行b.php a取得獨佔鎖,b只能等待,等a執行完解除鎖定後才能執行b,阻塞
例項2:A,B都使用共享鎖,不阻塞
a.php
$file = 'test.txt';
$fp = fopen($file, 'r');
if(flock($fp, LOCK_SH)){ // 取得共享鎖
sleep(10); // sleep 10秒
while(!feof($fp)){
echo fread($fp, 100);
}
flock($fp, LOCK_UN);
}
fclose($fp);
b.php
$file = 'test.txt';
$fp = fopen($file, 'r');
if(flock($fp, LOCK_SH)){ // 取得共享鎖
while(!feof($fp)){
echo fread($fp, 100);
}
flock($fp, LOCK_UN);
}
fclose($fp);
先執行a.php,然後執行b.php
b不需要等待a執行完就能輸出檔案內容,非阻塞
例項3:A,B都使用獨佔鎖寫檔案,阻塞
a.php
$file = 'test.txt';
$fp = fopen($file, 'a');
if(flock($fp, LOCK_EX)){ // 取得獨佔鎖
fwrite($fp, "Hello World\r\n"); // 寫入資料
sleep(10); // sleep 10秒,檔案被鎖定
fwrite($fp, "Hello PHP\r\n"); // 寫入資料
flock($fp, LOCK_UN); // 解鎖
}
fclose($fp);
b.php
$file = 'test.txt';
$fp = fopen($file, 'a');
if(flock($fp, LOCK_EX)){ // 取得獨佔鎖
fwrite($fp, "How Are You\r\n"); // 寫入資料
fwrite($fp, "Show Me The Money\r\n"); // 寫入資料
flock($fp, LOCK_UN); // 解鎖
}
fclose($fp);
先執行a.php,然後執行b.php
b需要等待a執行完,才能寫入資料,阻塞
例項4:LOCK_NB 鎖定時不阻塞,不等待
a.php
$file = 'test.txt';
$fp = fopen($file, 'a');
if(flock($fp, LOCK_EX)){ // 取得獨佔鎖
fwrite($fp, "Hello World\r\n"); // 寫入資料
sleep(10); // sleep 10秒,檔案被鎖定
fwrite($fp, "Hello PHP\r\n"); // 寫入資料
flock($fp, LOCK_UN); // 解鎖
}
fclose($fp);
b.php
$file = 'test.txt';
$fp = fopen($file, 'a');
if(flock($fp, LOCK_EX|LOCK_NB)){ // 取得獨佔鎖
fwrite($fp, "How Are You\r\n"); // 寫入資料
fwrite($fp, "Show Me The Money\r\n"); // 寫入資料
flock($fp, LOCK_UN); // 解鎖
}else{
echo 'file locked';
}
fclose($fp);
先執行a.php,然後執行b.php
b取不到獨佔鎖,不需要等待a執行完,而是直接返回取不到鎖提示,非阻塞
總結
使用共享鎖LOCK_SH,如果是讀取,不需要等待,但如果是寫入,需要等待讀取完成。
使用獨佔鎖LOCK_EX,無論寫入/讀取都需要等待。
LOCK_UN,無論使用共享/讀佔鎖,使用完後需要解鎖。
LOCK_NB,當被鎖定時,不阻塞,而是提示鎖定。
來自為知筆記(Wiz)