首先還是來介紹一下flock()的這個函數:
函數原型
bool flock (resource fp, int operation [, int & wouldblock])
要取得共享鎖定(讀取的程序),將 lock 設為 LOCK_SH(PHP 4.0.1 以前的版本設置為 1)。
<?php
$file = fopen("test.txt","w+");
// 排它性的鎖定
if (flock($file,LOCK_EX))
{
fwrite($file,"Write something");
// release lock
flock($file,LOCK_UN);
}
else
{
echo "Error locking file!";
}
fclose($file);
?>這是一個一般判斷的的例子。 對於實際的運用,必須將其添加到所有使用的文件腳本中
但注意:其函數無法再NFS或其他網絡文件系統中使用也無法在多線程服務器API中使用。
更一般的例子有
$fp =fopen("$DOCUMENT_ROOT/../orders/order.txt",'ab');//這里要注意/../帶來的安全性問題
flock($fp , LOCK_EX);
fwrite($fp,$outputstring);
flock($fp,LOCK_UN);
fclose($fp);這里注意如有兩個腳本同時申請對一個文件加鎖,會導致競爭條件關系,這時候應用DBMS解決 個人覺得使用flock()函數就是當有2個以上用戶同時對同一文件操作時,使用戶有序的排隊操作,避免出現混亂。
不知道可否用此函數來避免同時提交導致的刷分的現象
接下來看一個這個函數的代替用法
/*FLOCK的不可靠讓處理文件IO時很頭疼
這個函數降低了FLOCK的不可靠性
注意使用函數前后要IGNOR USER ABOUT以免用戶突然關閉瀏覽器造成文件沒寫完.
函數返回錯誤的幾種情況概率非常之小*/
<?php
//安全寫文件(不會沖突,不使用flock)請不斷刷新,數字會累加,不會錯過
//一旦返回錯誤,將可能是屬性$lockfile非0777錯誤(這種可能性極小)
//
function safewrite($filename,$content)
{
$long=0;
$lock_file=$filename.'.lock';
while($long<2)
{
clearstatcache();
if(file_exists($lock_file))
{
usleep(100);
$long=abs( date("s")-date ("s", filemtime($lock_file)));
continue;
}
else
{
@fclose(@fopen($lock_file,'w'));
$fp=@fopen($filename,'w');//無法打開
if($fp===FALSE)return FALSE;
$s=@fwrite($fp ,$content);
if($s===FALSE)return FALSE; //無法寫入
@fclose($fp);
unlink($lock_file);
return TRUE;
}
}
if(!unlink($lock_file))return FALSE;//無法刪除鎖文件
@fclose(@fopen($lock_file,'w'));
$fp=@fopen($filename,'w');
if($fp===FALSE)return FALSE; //無法打開
$s=@fwrite($fp ,$content);
if($s===FALSE)return FALSE;//無法寫入
@fclose($fp);
unlink($lock_file);
return TRUE;
}
ignore_user_abort (TRUE);
$n=file_get_contents('test');
$n++;
if(safewrite('test',$n))echo $n; else fopen('error','w');
ignore_user_abort (FALSE);
?>但是 /*本函數的缺陷是,當兩個進程同時發現$lockfile不存在,則同時建立文件,會造成沖突 雖然概率很小 數據庫有防死鎖機制,但目前PHP文件操作很難實現這個功能 如果使用flock,請務必在你的系統下進行測試*/ //可以這樣 flock($fp,LOCK_EX); sleep(5); /*然后在5秒之內用瀏覽器開始另一個進程 echo flock($fp,LOCK_SH); 看是否能獲得獨占鎖(或共享鎖) 如果不能獲得,則表明flock起作用*/還有一個測試方法
<?php
//本文件保存為flock.php,
ignore_user_abort (TRUE);
$fp=fopen('test','w');
flock($fp,LOCK_EX);
sleep(30);
ignore_user_abort (FALSE);//這里還是請大神考慮下,有一定安全隱患
?>
/*運行上文件后,30秒內運行下文件,即可判斷是否FLOCK正常;
30秒后程序停止,之后文件自動解鎖*/
<?php
//本文件保存為get_flock.php,一定要在執行flock.php后執行
$fp=fopen('test','w');
if( flock($fp,LOCK_EX|LOCK_NB))echo '當前獲得鎖定!如果flock.php正在運行,說明flock在你的系統上不能運行';
else echo '不能獲得鎖定,flock可以在你的系統上運行';
?>
