首先還是來介紹一下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可以在你的系統上運行';
?>