1. 程式人生 > 其它 >PHP中檔案鎖

PHP中檔案鎖

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)