细说php锁

bool flock ( int handle, int operation [, int &wouldblock] );
flock() 操做的 handle 必须是一个已经打开的文件指针。operation 能够是如下值之一:php

  1. 要取得共享锁定(读取程序),将 operation 设为 LOCK_SH(PHP 4.0.1 之前的版本设置为 1)
  2. 要取得独占锁定(写入程序),将 operation 设为 LOCK_EX(PHP 4.0.1 之前的版本中设置为 2)
  3. 要释放锁定(不管共享或独占),将 operation 设为 LOCK_UN(PHP 4.0.1 之前的版本中设置为 3)
  4. 若是你不但愿 flock() 在锁定时堵塞,则给 operation 加上 LOCK_NB(PHP 4.0.1 之前的版本中设置为 4)

 

建两个文件
(1) a.phphtml

?
$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
读取数据完整,但时间过长,他要等待写锁释放。spa

修改 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…
证实能够返回锁文件失败状态,而不是向上面同样要等好久。code

结论:
建议做文件缓存时,选好相关的锁,否则可能致使读取数据不完整,或重复写入数据。
file_get_contents 好像选择不了锁,不知道他默认用的什么锁,反正和不锁获得的输出同样,是不完整的数据。
我是要作文件缓存,因此只须要知道是否有写锁存在便可,有的话就查数据库就能够了。
测试环境:Linux(Ubuntu 6) , PHP 5.1.2 , Apache 2htm

再转:blog

文件锁有两种:共享锁和排他锁,也就是读锁(LOCK_SH)和写锁(LOCK_EX) 
文件的锁通常这么使用:
  1. $fp = fopen("filename""a");   
  2. flock($fp, LOCK_SH) or die("lock error")   
  3. $str = fread($fp, 1024);   
  4. flock($fp, LOCK_UN);   
  5. 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写完并释放锁以后才进行读。 

还有一篇也写得不错的博文:

http://hxsdit.com/1110

相关文章
相关标签/搜索