Maison >développement back-end >tutoriel php >flock — 轻便的咨询文件锁定_PHP教程
bool flock ( resource $handle , int $operation [, int &$wouldblock ] )
handle
文件系统指针,是典型地由 fopen() 创建的 resource (资源)。
operation 可以是以下值之一:
1. LOCK_SH 取得共享锁定(读取的程序)。
2. LOCK_EX 取得独占锁定(写入的程序。
3. LOCK_UN 释放锁定(无论共享或独占)。
4.如果不希望 flock() 在锁定时堵塞,则是 LOCK_NB (Windows 上还不支持)。
wouldblock
如果锁定会堵塞的话(EWOULDBLOCK 错误码情况下),可选的第三个参数会被设置为 TRUE 。(Windows 上不支持)
返回值
成功时返回 TRUE , 或者在失败时返回 FALSE 。
在 PHP 5.3.2版本之前,锁也会被 fclose() 释放(在脚本结束后会自动调用),现在要解锁必须手动进行( flock ( $fp , LOCK_UN );// 释放锁定)。
当用一个多线程服务器 API(比如 ISAPI)时,可能不可以依靠 flock() 来保护文件,因为运行于同一服务器实例中其它并行线程的 PHP 脚本可以对该文件进行处理。(?)
eg:1
file_get_contents 和 file 有时读取一非空文件时返回空,如下例
code1锁定期间,code2输出的都是空,code3会等待code1释放锁定后返回获取的内容
code1
<?<span>php </span><span>$fo</span> = <span>fopen</span>('abc.txt', 'r+'<span>); </span><span>flock</span>(<span>$fo</span>,<span> LOCK_EX); </span><span>sleep</span>(10<span>); </span><span>flock</span>(<span>$fo</span>, LOCK_UN);
code2
<?<span>php </span><span>var_dump</span>(<span>file_get_contents</span>('abc.txt'<span>)); </span><span>var_dump</span>(<span>file</span>('abc.txt'));
code3
<?<span>php </span><span>$con</span> = getContents('abc.txt'<span>); </span><span>print_r</span>(<span>$con</span><span>); </span><span>function</span> getContents(<span>$path</span>, <span>$waitIfLocked</span> = <span>true</span><span>) { </span><span>if</span>(!<span>file_exists</span>(<span>$path</span><span>)) { </span><span>throw</span> <span>new</span> <span>Exception</span>('File "'.<span>$path</span>.'" does not exists'<span>); } </span><span>else</span><span> { </span><span>$fo</span> = <span>fopen</span>(<span>$path</span>, 'r'<span>); </span><span>$locked</span> = <span>flock</span>(<span>$fo</span>, LOCK_SH, <span>$waitIfLocked</span><span>); </span><span>if</span>(!<span>$locked</span><span>) { </span><span>return</span> <span>false</span><span>; } </span><span>else</span><span> { </span><span>$cts</span> = <span>file_get_contents</span>(<span>$path</span><span>); </span><span>flock</span>(<span>$fo</span>,<span> LOCK_UN); </span><span>fclose</span>(<span>$fo</span><span>); </span><span>return</span> <span>$cts</span><span>; } } } </span>
eg:2
本机运行结果和下面的不一致,LOCK_SH时能写入(???)
下面的是手册上的例子
I just spend a long time to understand why write function returns me "0", on a basic file opening and then writing.
I discovered that if you use LOCK_SH and then you write something, that will not work :
<?<span>php </span><span>$fp</span> = <span>fopen</span>('file.txt', 'a'<span>); </span><span>flock</span>(<span>$fp</span>,<span>LOCK_SH); </span><span>$written</span> = <span>fputs</span>(<span>$fp</span>, 'data'<span>); </span><span>var_dump</span>(<span>$written</span>); <span>//</span><span> 0 and file is not changed</span> <span>fclose</span>(<span>$fp</span>);
eg:3
写代码来解决多进程线程同时读写一个文件的问题:
PHP是没有多线程概念的,尽管如此我们仍然可以用“不完美”的方法来模拟多线程。
简单的说,就是队列处理。通过对文件进行加锁和解锁,来实现。当一个文件被一个用户操作时,
该文件是被锁定的,其他用户只能等待,确实不够完美,但是也可以满足一些要求不高的应用
<?<span>php </span><span>function</span> T_put(<span>$filename</span>,<span>$string</span><span>){ </span><span>$fp</span> = <span>fopen</span>(<span>$filename</span>,’a'<span>); //追加方式打开 if (flock($fp, LOCK_EX)){ //加写锁 fputs($fp,$string); //写文件 flock($fp, LOCK_UN); //解锁 } fclose($fp); } function T_get($filename,$length){ $fp = fopen($filename,’r</span>'); <span>//</span><span>追加方式打开 </span> <span>if</span> (<span>flock</span>(<span>$fp</span>, LOCK_SH)){ <span>//</span><span>加读锁 </span> <span>$result</span> = <span>fgets</span>(<span>$fp</span>,<span>$length</span>); <span>//</span><span>读取文件 </span> <span>flock</span>(<span>$fp</span>, LOCK_UN); <span>//</span><span>解锁 </span> <span>} </span><span>fclose</span>(<span>$fp</span><span>); </span><span>return</span> <span>$result</span><span>; }</span>