bool flock ( int handle, int operation [, int &wouldblock] );
flock() 操作的 handle 必须是一个已经打开的文件指针。operation 可以是以下值之一:
- 要取得共享锁定(读取程序),将 operation 设为 LOCK_SH(PHP 4.0.1 以前的版本设置为 1)
- 要取得独占锁定(写入程序),将 operation 设为 LOCK_EX(PHP 4.0.1 以前的版本中设置为 2)
- 要释放锁定(无论共享或独占),将 operation 设为 LOCK_UN(PHP 4.0.1 以前的版本中设置为 3)
- 如果你不希望 flock() 在锁定时堵塞,则给 operation 加上 LOCK_NB(PHP 4.0.1 以前的版本中设置为 4)
建两个文件
(1) a.php
$file = "temp.txt" ;
$fp = fopen ( $file , 'w' );
if ( flock ( $fp , LOCK_EX)){
fwrite( $fp , "abc\n" );
sleep(10);
fwrite( $fp , "123\n" );
flock ( $fp , LOCK_UN);
} fclose( $fp );
|
(2) b.php
$file = "temp.txt" ;
$fp = fopen ( $file , 'r' );
echo fread ( $fp , 100);
fclose( $fp );
|
运行 a.php 后,马上运行 b.php ,可以看到输出:
abc
等 a.php 运行完后运行 b.php ,可以看到输出:
abc
123
显然,当 a.php 写文件时数据太大,导致时间比较长时,这时 b.php 读取数据不完整
修改 b.php 为:
$file = "temp.txt" ;
$fp = fopen ( $file , 'r' );
if ( flock ( $fp , LOCK_EX)){
echo fread ( $fp , 100);
flock ( $fp , LOCK_UN);
} else {
echo "Lock file failed...\n" ;
} fclose( $fp );
|
运行 a.php 后,马上运行 b.php ,可以发现 b.php 会等到 a.php 运行完成后(即 10 秒后)才显示:
abc
123
读取数据完整,但时间过长,他要等待写锁释放。
修改 b.php 为:
$file = "temp.txt" ;
$fp = fopen ( $file , 'r' );
if ( flock ( $fp , LOCK_SH | LOCK_NB)){
echo fread ( $fp , 100);
flock ( $fp , LOCK_UN);
} else {
echo "Lock file failed...\n" ;
} fclose( $fp );
|
运行 a.php 后,马上运行 b.php ,可以看到输出:
Lock file failed…
证明可以返回锁文件失败状态,而不是向上面一样要等很久。
结论:
建议作文件缓存时,选好相关的锁,不然可能导致读取数据不完整,或重复写入数据。
file_get_contents 好像选择不了锁,不知道他默认用的什么锁,反正和不锁得到的输出一样,是不完整的数据。
我是要做文件缓存,所以只需要知道是否有写锁存在即可,有的话就查数据库就可以了。
测试环境:Linux(Ubuntu 6) , PHP 5.1.2 , Apache 2
再转:
文件锁有两种:共享锁和排他锁,也就是读锁(LOCK_SH)和写锁(LOCK_EX)
文件的锁一般这么使用:
文件的锁一般这么使用:
- $fp = fopen("filename", "a");
- flock($fp, LOCK_SH) or die("lock error")
- $str = fread($fp, 1024);
- flock($fp, LOCK_UN);
- fclose($fp);
注意fwrite之后,文件立即就被更新了,而不是等fwrite然后fclose之后文件才会更新,这个可以通过在fwrite之后fclose之前读取这个文件进行检查
但是什么时候使用lock_ex什么时候使用lock_sh呢?
读的时候:
如果不想出现dirty数据,那么最好使用lock_sh共享锁。可以考虑以下三种情况:
1. 如果读的时候没有加共享锁,那么其他程序要写的话(不管这个写是加锁还是不加锁)都会立即写成功。如果正好读了一半,然后被其他程序给写了,那么读的后一半就有可能跟前一半对不上(前一半是修改前的,后一半是修改后的)
2. 如果读的时候加上了共享锁(因为只是读,没有必要使用排他锁),这个时候,其他程序开始写,这个写程序没有使用锁,那么写程序会直接修改这个文件,也会导致前面一样的问题
3. 最理想的情况是,读的时候加锁(lock_sh),写的时候也进行加锁(lock_ex),这样写程序会等着读程序完成之后才进行操作,而不会出现贸然操作的情况
写的时候:
如果多个写程序不加锁同时对文件进行操作,那么最后的数据有可能一部分是a程序写的,一部分是b程序写的
如果写的时候加锁了,这个时候有其他的程序来读,那么他会读到什么东西呢?
1. 如果读程序没有申请共享锁,那么他会读到dirty的数据。比如写程序要写a,b,c三部分,写完a,这时候读读到的是a,继续写b,这时候读读到的是ab,然后写c,这时候读到的是abc.
2. 如果读程序在之前申请了共享锁,那么读程序会等写程序将abc写完并释放锁之后才进行读。
还有一篇也写得不错的博文:
相关推荐
PHP文件锁同步实例 请参考文档: http://blog.csdn.net/u014175572/article/details/53381049 和 http://www.jb51.net/article/24962.htm请参考文档: http://blog.csdn.net/u014175572/article/details/53381049 和...
为了解决这个问题,PHP 提供了一种机制——文件锁(File Locking)。文件锁允许在读写文件时设置锁定,确保在同一时刻只有一个进程能够对文件进行操作。本篇文章将深入探讨如何使用 PHP 的 `flock` 函数来实现文件锁...
在计算机程序设计领域,文件锁是一种同步机制,它用于防止多个进程或线程同时对同一文件进行修改,以避免数据冲突和数据不一致的问题。在PHP中,flock函数就是用于实现文件锁定的一种机制。 flock是PHP提供的一个轻...
在PHP中,我们可以使用`flock()`函数实现文件锁,这是最常见的阻塞锁实现方式。例如,当多个请求同时尝试写入同一个文件时,第一个请求会获得文件锁,其他请求则会被阻塞,直到第一个请求完成写入并释放锁。 接着,...
本篇文章将详细探讨PHP如何利用文件锁来处理高并发问题,并通过实例分析阻塞模式和非阻塞模式的文件锁在实际应用中的差异。 ### 一、文件锁的基本概念 文件锁是操作系统提供的一种机制,用于控制对文件的并发访问...
在讨论PHP中的文件锁、互斥锁以及读写锁时,我们首先需要了解锁在并发编程中的作用。锁是用来防止多个进程或线程同时访问同一资源,从而避免数据竞争和不一致问题。在PHP中,文件锁是一种机制,可以用来控制多个脚本...
由于PHP文件锁的这些限制,在某些高要求的并发环境中,可能需要使用其他更可靠的文件锁定技术,比如操作系统级别的文件锁命令,或者使用数据库表锁来进行并发控制。例如,在某些场景下,人们可能会考虑使用MySQL的...
echo "无法获取文件锁"; } fclose($fp); ``` 在此场景下,shell脚本可能通过定时任务或系统服务来启动和监控这个PHP后台进程,确保文件始终处于锁定状态。当然,实际应用中还需要考虑异常处理、错误恢复、资源释放...
PHP 文件锁与进程锁的使用示例知识点总结: 1. 文件锁与进程锁概念 文件锁和进程锁是两种不同的锁定机制,它们在并发控制中有着不同的应用场景和作用。文件锁用于对文件的读写操作进行控制,防止多个进程同时对同一...
在PHP开发中,特别是在处理并发访问的场景,如日志记录、文件共享等,文件锁是一种重要的机制,用于确保同一时间只有一个进程可以访问特定的文件资源。文件锁可以帮助避免数据的混乱,保证数据的一致性。本文将详细...
1. 文件锁:基于文件系统,简单易用,但可能受到文件系统的限制,如并发性能较低,不适合分布式环境。 2. Redis锁:使用Redis数据库实现,适合分布式环境,具有较高的性能和可扩展性,但需要额外的Redis服务器支持。...
在PHP编程中,确保线程安全特别是在处理文件时至关重要,因为多个请求可能同时...正确地使用文件锁可以避免数据竞争,保证程序的正确性和一致性。在编写多线程或多进程的PHP脚本时,了解并应用这些技术是至关重要的。
文件锁是并发编程中的一个重要概念,它用于确保数据在多线程或多个进程访问时的完整性。在PHP中,flock()是一个文件锁定的函数,用于防止多个进程同时对同一个文件执行写操作,从而避免数据的损坏。本文将详细介绍...
接下来,我们分析提供的`RedisLock.php`文件。这是一个实现Redis锁的类,通常会包含以下功能: - 初始化连接到Redis服务器 - 创建加锁方法,可能接受方法名、用户ID等参数,用于生成唯一键 - 设置锁的过期时间和自动...