1. 程式人生 > >PHP檔案鎖解析 flock()

PHP檔案鎖解析 flock()

1、普通寫入和讀取
b.php寫入

$file = 'tt.txt';
$fp = fopen($file,'a+b');
fwrite($fp,"c");
sleep(3);
fwrite($fp,"a");


c.php讀取

$file = 'tt.txt';
$fp = fopen($file,'rb');
echo fread($fp,1000);
fclose($fp);


結果:b檔案一邊寫入,c檔案可以一邊讀取,不存在鎖的情況,c.php不用等待,當有內容時就能夠立刻讀取到內容


2、寫檔案使用寫鎖LOCK_EX
b.php寫入

$file = 'tt.txt';
$fp = fopen($file,'a+b');
if(flock($fp,LOCK_EX)){
fwrite($fp,"c\r\n");
sleep(3);
fwrite($fp,"a\r\n");
flock($fp,LOCK_UN);
}

c.php讀取

$file = 'tt.txt';
$fp = fopen($file,'rb');
echo fread($fp,1000);
fclose($fp);

結果:現在鎖的情況。即,b檔案在寫但還沒有寫完的時候,c檔案不能讀取到內容,只有b寫完了,c能才獲得內容。

3、寫入鎖定,讀取檔案使用不堵塞,即當發生其他檔案在寫而鎖定時,會返回被鎖定的標誌而不等待
b.php寫入

$file = 'tt.txt';
$fp = fopen($file,'a+b');
if(flock($fp,LOCK_EX)){
fwrite($fp,"c\r\n");
sleep(3);
fwrite($fp,"a\r\n");
flock($fp,LOCK_UN);
}

c.php讀取

$file = 'tt.txt';
$fp = fopen($file,'rb');
if(flock($fp,LOCK_SH | LOCK_NB)){//LOCK_NB需要與前面3種狀態配合才能使用
echo fread($fp,1000);
flock($fp,LOCK_UN);
}else{
echo 'lock file failed...';
}
4、共享鎖
a.php讀,使用共享鎖
$file = 'tt.txt';
$fp = fopen($file,'rb');
if(flock($fp,LOCK_SH)){
echo fread($fp,1000);
sleep(3);
flock($fp,LOCK_UN);
}
fclose($fp);

b.php寫鎖定
$file = 'tt.txt';
$fp = fopen($file,'a+b');
if(flock($fp,LOCK_EX)){//這裡LOCK_EX如果換成LOCK_SH則完全寫入不了,因為一開始就被自已檔案的程式給共享鎖了
fwrite($fp,"c\r\n");
flock($fp,LOCK_UN);
}

c.php同a.php共享讀
$file = 'tt.txt';
$fp = fopen($file,'rb');
if(flock($fp,LOCK_SH)){
echo fread($fp,1000);
flock($fp,LOCK_UN);
}
fclose($fp);

先執行a.php,再執行b.php,然後立刻執行c.php
結果為:a中可以讀到檔案,b中的寫需要等a讀完才能寫,c中在a共享鎖的情況下也可以讀到同個檔案的內容


LOCK_EX與LOCK_SH區別:
LOCK_EX是寫鎖定,即寫入的時候檔案處於寫鎖狀態,別人不能寫也不能讀。如果直接讀,將是一段時間的等待,別人寫完了,解鎖後才恢復,也才能讀
LOCK_SH是共享鎖定,即讀的時候檔案處於共享鎖狀態,別人只能讀,不能寫。如果直接寫,將是一段時間的等待,別人讀完了,解鎖後才恢復,也才能寫

LOCK_UN:用於解鎖前面兩種狀態
LOCK_NB:在讀取或者寫入時,如果檔案被鎖,則立刻返回通知訪問的檔案被鎖了,不用再等待。不能單使用需要與前面兩種方式配合使用,例如:
flock($fp,LOCK_SH | LOCK_NB)
用於判定有些人在寫,而有些人在讀同個檔案的情況,使用其立刻知道當前為寫鎖狀態而不用等待

flock($fp,LOCK_EX | LOCK_NB)用於判定可能多個人在寫同個檔案的情況,使用其立刻知道當前為共享鎖狀態而不用等待