Heim  >  Artikel  >  Backend-Entwicklung  >  PHP资料函数flock

PHP资料函数flock

WBOY
WBOYOriginal
2016-06-13 12:50:28761Durchsuche

PHP文件函数flock

? ? ? ? 并发情况下,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内部调的是宿主文件系统,自然会把锁请求排队处理。

?

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn