并发情况下,PHP该如何写文件?其实这个问题不只是PHP面临的问题。不管是线程还是进程,当并发写的时候,都会遇到共享资源写冲突。软件开发过程中,写冲突无处不在,比如多线程写共享变量,比如数据库多连接并发写数据,比如多进程写文件等等。那么这些都该如何处理呢?目前普遍的处理办法就是给共享资源上独占锁(写锁)。
PHP在第三版的时候就提供了一个函数flock,顾名思义,文件锁操作函数。文件锁机制是依赖于宿主文件系统的,也就是说,如何个锁法,是宿主文件系统说了算,flock只是个外壳函数,里面调用了文件系统的锁机制。
锁的话,分为两种类型,读锁和写锁。写锁也叫排它锁、独占锁,就是一个线程或进程独占资源,别的线程或进程无法使用资源,保证写数据不受干扰,不冲突;读锁也叫共享锁,允许多个线程或进程同时读,但不能有写的操作。
函数原型:
<?php flock ($handle, $operation, &$wouldblock = null); ?>
参数说明:
$handle //文件指针
$operation //锁类型
$operation 有几个可用值:LOCK_EX【写锁】、LOCK_SH【读锁】、LOCK_UN【释放锁】
看个例子吧
<?php function fileWrite($file) { $fp = fopen($file, 'a'); flock($fp, LOCK_EX);//上写锁 /*写数据*/ fwrite($fp, "1"); fwrite($fp, "2"); fwrite($fp, "3\r\n"); flock($fp, LOCK_UN);//释放锁 fclose($fp); } fileWrite('D:/txt.txt'); ?>用Jmeter做下并发测试,执行3000次请求,会发现文件里有3000行123(不考虑apache或nginx的性能瓶颈)。
在用Jmeter做并发测试的时候,用记事本打开这个文件,改点东西,然后点击保存,你会发现下图情况
这就是因为文件上锁了,记事本进程无法写入。
前边说了,flock函数的锁机制实际上是文件系统的锁机制,它封装了某些类型文件系统的锁机制,有些文件系统flock不支持,据PHP手册上说,FAT、NTF等这种老式文件系统和网络文件系统,flock不支持。本人没测过。
PHP手册还说,flock是进程级别的,多线程的时候不起作用。可能大家就要有疑惑了,PHP又没线程的概念。那把PHP放在支持多线程的服务器上呢,大家想想看。测一测。
分析到这一步呢,会发现flock依赖宿主,对环境有要求,这就深深的伤害了代码的可移植性。怕啦!!别怕,其实伤害也没多深,flock还是能满足大部分环境的。
针对flock的移植性稍有些不足,大家就开始研究替代办法,我也关注了下,发现网上流传着下面这样的代码
<?php function fileWrite($file,$content) { $lock = $file.'.lock'; while (true) { if (file_exists($lock)) { usleep(100); } else { touch($lock);//上锁 file_put_contents($file, $content, FILE_APPEND);//写文件 @unlink($lock);//删除锁 break; } } } fileWrite('D:/txt.txt','i m a phper'); ?>
你觉着这段代码有锁作用么??测测!!其实都不用测,一看就锁不住,file_exists本来就可以并行执行,当两进程同时执行到file_exists,判断所谓的锁文件不存在,结果还不是冲突着呢。
锁,实际上是将并发访问排队阻塞串行化,然后依次处理访问,上边这段代码连排队都没有,怎么能上锁呢。
这时候大家可能又会问多个进程同时执行flock,不也是并行的么?是,执行flock是并行的,这只是代表申请锁是并行的,flock内部调的是宿主文件系统,自然会把锁请求排队处理。
相关推荐
主要介绍了PHP文件锁函数flock()详细介绍,本文着重对flock函数的作用和参数讲解,以及使用需要注意的问题,需要的朋友可以参考下
脚本之家小编今天将为大家详解关于php中文件锁函数flock函数用法简介,希望通过本文的介绍大家对于Linux方面能够更加的了解
9.1.7 使用flock锁住文件 9.1.8 seek和tell函数 9.1.9 打开文件读写 9.1.10 管道打开 9.2 传送参数 9.2.1 ARGV数组 9.2.2 ARGV和Null文件句柄 9.2.3 eof函数 9.2.4 -i开关:原位编辑文件 ...
文件读取函式 //文件读取函式 function PHP_Read($file_name) { $fd=fopen($file_name,r); while($bufline=fgets($fd, 4096)){ $buf.=$bufline; } fclose($fd); return $buf; } ?> 文件写入函式 //文件...
PHP文件读取函式 复制代码 代码如下: //文件读取函式 function PHP_Read($file_name) { $fd=fopen($file_name,r); while($bufline=fgets($fd, 4096)){ $buf.=$bufline; } fclose($fd); return $buf; } ?>...
锁 标准的 PHP flock函数很难测试。 这个库为flock提供了一个现代的、面向对象的包装器。安装将以下内容添加到您的composer.json : { " require " : { " benconstable/lock " : " ~1.0 " }}用法 <?php$ lock = ...
本文提供了文件加锁函数以及使用示例。文件加锁功能也可以用来获得独享的处理空间,防止脚本执行发生同步错误。 复制代码 代码如下: <?php /******************************************************************...
对抗网络扫描的手段 系统补丁Patch 禁止与系统服务信息有关的回应 停止系统服务 安装防火墙软件或者个人防火墙软件 使用入侵检测系统 提供系统安全的日志和审计功能 一些小而有效的技巧 网络安全ppt(1)全文共65页,...
对抗网络扫描的手段 系统补丁Patch 禁止与系统服务信息有关的回应 停止系统服务 安装防火墙软件或者个人防火墙软件 使用入侵检测系统 提供系统安全的日志和审计功能 一些小而有效的技巧 网络安全ppt(2)全文共65页,...