2
回答
PHP文件锁刷新后为何能写入?

想给一个30秒的cron任务加个文件锁的功能,防止30秒任务没完成又开始下一个任务。

所以想用php文件锁功能来做,起先做了个如下的实验:

1.php

<?php
$a = '12345';
$f = fopen('1.txt', 'a');
$as = flock($f, LOCK_EX);
sleep(10);
fwrite($f, $a);
flock($f, LOCK_UN);
fclose($f);



2.php

<?php

$f = fopen('1.txt', 'a');
if(fwrite($f, '99999')){
	echo 'write ok';
}else{
	echo 'no no no.';
}
fclose($f);



选择独占锁,在锁上的时候不能读写此文件。

第一次我用浏览器打开1.php,这10秒内我打开2.php就会echo 出 no no no ,10秒之后再刷新2.php,会echo 出 write ok,这时打开1.txt,内容会是9999912345,和预期一样。

接下来的我就不理解了。

我再次刷新1.php,按说这时候1.php里的代码重新执行,1.txt重新上锁,10秒内再刷新2.php还是会echo 出 no no no(我认为的),但是此时我刷新2.php后发现echo出了 write ok,打开1.txt发现内容99999被写入了。

第二次没有加锁吗?我在1.php里加了一句 $as = flock($f, LOCK_EX);echo $as;输出的是1,也就是加锁成功了,那为什么2.php在1.php第二次运行的时候还能写入加锁的文件呢?

PHP
举报
itsingfeng
发帖于1年前 2回/242阅
共有2个答案 最后回答: 1年前
两个PHP文件,在写操作前都需要 flock($fp,LOCK_EX) 申请排它锁,比如下面我把数组保存到文件,通过排它锁LOCK_EX保证请求并发时数据的正确性.

foo1.php:
<?php
header('Content-Type: text/plain; charset=utf-8');
$arr = require 'arr.php'; //arr.php内容为 <?php return array();
$fp = fopen('arr.php', 'r+'); //读写方式打开,将文件指针指向文件头
if(flock($fp,LOCK_EX)) { //阻塞到获取排它锁
    $arr['name'] = 'foo1';
    ftruncate($fp, 0); //截断文件
    fwrite($fp,'<?php return '.var_export($arr, true).';');
    var_export($arr);
    fflush($fp); //在释放锁之前刷新输出
    sleep(10); //睡眠10秒,在此期间访问foo2.php将被阻塞
    flock($fp, LOCK_UN); //释放锁定
}
fclose($fp);

foo2.php:
<?php
header('Content-Type: text/plain; charset=utf-8');
$arr = require 'arr.php';
$fp = fopen('arr.php', 'r+');
if(flock($fp,LOCK_EX)) {
    $arr['name'] = 'foo2';
    ftruncate($fp, 0);
    fwrite($fp,'<?php return '.var_export($arr, true).';');
    var_export($arr);
    fflush($fp);
    flock($fp, LOCK_UN);
}
fclose($fp);
--- 共有 1 条评论 ---
itsingfeng谢谢E神的解答,我刚才也在不断尝试,试了两个文件都带锁访问,然后依然第一次请求1.php时再请求2.php会阻塞,阻塞完了才执行2.php,然后刷新一下1.php,这时候再次刷新2.php就不会阻塞,直接执行成功,请问这是什么原理? 1年前 回复
顶部