PHP函数-flock()与之替代方法的看法
首先还是来介绍一下flock()的这个函数:函数原型
bool flock (resource fp, int operation [, int & wouldblock])
要取得共享锁定(读取的程序),将 lock 设为 LOCK_SH(PHP 4.0.1 以前的版本设置为 1)。
要取得独占锁定(写入的程序),将 lock 设为 LOCK_EX(PHP 4.0.1 以前的版本中设置为 2)。
要释放锁定(无论共享或独占),将 lock 设为 LOCK_UN(PHP 4.0.1 以前的版本中设置为 3)。
如果不希望 flock() 在锁定时堵塞,则给 lock 加上 LOCK_NB(PHP 4.0.1 以前的版本中设置为 4)。(这是引用W3school的)
<?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在你的系统上不能运行';
elseecho '不能获得锁定,flock可以在你的系统上运行';
?>
页:
[1]