共享锁
测试方法,读取两次文件,中间增加延时,在延时的时候执行写入方法
方法:
/**
* 读取文件内容
*/
protected function read()
{
$lockFile = __DIR__.'/test.log'; // 文件地址
$fp = fopen($lockFile, 'r'); // 打开文件
dump(flock($fp, LOCK_SH)); // 加锁(共享锁)
dump(fread($fp, 1024)); // 读取文件内容
sleep(10); // 增加延时,用于写入测试
fseek($fp, 0); // 将文件指针指向文件开头
dump(fread($fp, 1024)); // 再次读取文件内容
flock($fp, LOCK_UN); // 释放锁
fclose($fp); // 关闭文件
}
/**
* 写入文件内容(第一次,不用锁验证)
*/
protected function write()
{
$lockFile = __DIR__.'/test.log';
$fp = fopen($lockFile, 'r+');
fwrite($fp, 'test:'.date('Y-m-d H:i:s').PHP_EOL);
fclose($fp);
}
/**
* 写入文件内容(第二次,用锁验证)
*/
protected function write2()
{
$lockFile = __DIR__.'/test.log';
$fp = fopen($lockFile, 'r+');
if(!flock($fp, LOCK_EX)){
echo '文件被锁定';
fclose($fp);
exit;
}
fwrite($fp, 'test:'.date('Y-m-d H:i:s'));
fclose($fp);
}
测试文件初始内容:
第一次测试结果:
结果两次读取到的内容是不同的,此时看来共享锁是没有任何作用的。
第二次测试结果
结果两次读取到的内容是相同的
注意:
1、我在写入文件的时候用的r+,如果用w+的话,读取方法第二次读取到的内容会是个空,关于这个可以看看fopen函数的介绍。
2、我在第二次的写入方法中flock是没有增加LOCK_NB所以写入方法不会进入if的判断。这个参数代表了flock如果发现文件被加锁了是否要等待执行,也就是flock的阻塞和非阻塞
独占锁
独占锁就很好理解了,加锁后其他进程不允许读和写。
测试方法和上面一样,将读取方法的LOCK_SH改为LOCK_EX
方法:
/**
* 读取/写入文件
*/
protected function writeAndRead()
{
$lockFile = __DIR__.'/test.log';
$fp = fopen($lockFile, 'r+');
dump(fwrite($fp, 'test:'.date('Y-m-d H:i:s'))); // 写入文件内容
dump(fread($fp, 1024)); // 再次读取文件内容
fclose($fp);
}
测试结果:
总结
文件锁的锁和字面意思是不一样的,最初我理解为加锁后其他进程不能对文件进行相应操作。测试后发现这个锁相当于给文件增加了一个属性并赋值为已上锁,其他进程需要每次获取这个属性从而来确认文件是否可以操作。
1、进程A增加共享锁,进程B增加共享锁,正常执行(共享锁可以增加多个)
2、进程A增加共享锁,进程B增加独占锁,进程B阻塞等待进程A执行完成(增加了共享锁的文件不可以增加独占锁)
3、进程A增加独占锁,进程B不论增加共享锁还是独占锁都是阻塞等待进程A执行完成
4、如果不想让进程B阻塞,增加LOCK_NB