php文件鎖

bool flock ( int handle, int operation [,int &wouldblock] );
flock() 操作的 handle 必須是一個已經打開的文件指針。operation 可以是以下值之一:

要取得共享鎖定(讀取程序),將 operation 設爲 LOCK_SH(PHP 4.0.1 以前的版本設置爲 1)

要取得獨佔鎖定(寫入程序),將 operation 設爲 LOCK_EX(PHP 4.0.1 以前的版本中設置爲 2)

要釋放鎖定(無論共享或獨佔),將 operation 設爲 LOCK_UN(PHP 4.0.1 以前的版本中設置爲 3)

如果你不希望 flock() 在鎖定時堵塞,則給 operation 加上 LOCK_NB(PHP 4.0.1 以前的版本中設置爲 4)

建兩個文件

(1) a.php

$file = "temp.txt";    
$fp = fopen($file , 'w');    
if(flock($fp , LOCK_EX)){    
     fwrite($fp , "abc\n");    
     sleep(10);    
     fwrite($fp , "123\n");    
    flock($fp , LOCK_UN);    
}    
fclose($fp);

(2) b.php

$file = "temp.txt";    
$fp = fopen($file , 'r');    
echo fread($fp , 100);    
fclose($fp);

運行 a.php 後,馬上運行b.php ,可以看到輸出:
abc
等 a.php 運行完後運行 b.php ,可以看到輸出:
abc
123
顯然,當 a.php 寫文件時數據太大,導致時間比較長時,這時b.php 讀取數據不完整

修改 b.php 爲:

$file = "temp.txt";    
$fp = fopen($file , 'r');    
if(flock($fp , LOCK_EX)){    
    echo fread($fp , 100);    
    flock($fp , LOCK_UN);    
} else{    
    echo "Lock file failed...\n";    
}    
fclose($fp);

運行 a.php 後,馬上運行b.php ,可以發現 b.php 會等到 a.php 運行完成後(即 10 秒後)才顯示:
abc
123
讀取數據完整,但時間過長,他要等待寫鎖釋放。

修改 b.php 爲:

$file = "temp.txt";    
$fp = fopen($file , 'r');    
if(flock($fp , LOCK_SH | LOCK_NB)){    
    echo fread($fp , 100);    
    flock($fp , LOCK_UN);    
} else{    
    echo "Lock file failed...\n";    
}    
fclose($fp);

運行 a.php 後,馬上運行b.php ,可以看到輸出:
Lock file failed…
證明可以返回鎖文件失敗狀態,而不是向上面一樣要等很久。

結論:
建議作文件緩存時,選好相關的鎖,不然可能導致讀取數據不完整,或重複寫入數據。
file_get_contents 好像選擇不了鎖,不知道他默認用的什麼鎖,反正和不鎖得到的輸出一樣,是不完整的數據。
我是要做文件緩存,所以只需要知道是否有寫鎖存在即可,有的話就查數據庫就可以了。
測試環境:Linux(Ubuntu 6) , PHP 5.1.2 , Apache 2

再轉:

文件鎖有兩種:共享鎖和排他鎖,也就是讀鎖(LOCK_SH)和寫鎖(LOCK_EX) 
文件的鎖一般這麼使用:
$fp = fopen("filename", "a");   
flock($fp, LOCK_SH) or die("lock error")   
$str = fread($fp, 1024);   
flock($fp, LOCK_UN);   
fclose($fp);

注意fwrite之後,文件立即就被更新了,而不是等fwrite然後fclose之後文件纔會更新,這個可以通過在fwrite之後fclose之前讀取這個文件進行檢查 

但是什麼時候使用lock_ex什麼時候使用lock_sh呢? 

讀的時候: 
如果不想出現dirty數據,那麼最好使用lock_sh共享鎖。可以考慮以下三種情況: 
1. 如果讀的時候沒有加共享鎖,那麼其他程序要寫的話(不管這個寫是加鎖還是不加鎖)都會立即寫成功。如果正好讀了一半,然後被其他程序給寫了,那麼讀的後一半就有可能跟前一半對不上(前一半是修改前的,後一半是修改後的) 
2. 如果讀的時候加上了共享鎖(因爲只是讀,沒有必要使用排他鎖),這個時候,其他程序開始寫,這個寫程序沒有使用鎖,那麼寫程序會直接修改這個文件,也會導致前面一樣的問題 
3. 最理想的情況是,讀的時候加鎖(lock_sh),寫的時候也進行加鎖(lock_ex),這樣寫程序會等着讀程序完成之後才進行操作,而不會出現貿然操作的情況 

寫的時候: 
如果多個寫程序不加鎖同時對文件進行操作,那麼最後的數據有可能一部分是a程序寫的,一部分是b程序寫的 
如果寫的時候加鎖了,這個時候有其他的程序來讀,那麼他會讀到什麼東西呢? 
1. 如果讀程序沒有申請共享鎖,那麼他會讀到dirty的數據。比如寫程序要寫a,b,c三部分,寫完a,這時候讀讀到的是a,繼續寫b,這時候讀讀到的是ab,然後寫c,這時候讀到的是abc. 
2. 如果讀程序在之前申請了共享鎖,那麼讀程序會等寫程序將abc寫完並釋放鎖之後才進行讀。 

還有一篇也寫得不錯的博文:

http://hxsdit.com/1110



轉自 http://www.cnblogs.com/chenwenbiao/archive/2011/08/01/2123905.html

作者 chenwenbiao

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章