PHP flock文件锁详解介绍

为了确保操作的有效性和完整性,可以通过锁机制将并发状态转换成串行状态.作为锁机制中的一种,PHP的文件锁也是为了应对资源竞争.假设一个应用场景,在存在较大并发的情况下,通过fwrite向文件尾部多次有序的写入数据,不加锁的情况下会发生什么?多次有序的写入操作相当于一个事务,我们此时需要保证这个事务的完整性.

bool flock ( int handle, int operation [, int &wouldblock] );

flock() 操作的 handle 必须是一个已经打开的文件指针.operation 可以是以下值之一:

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.php

  1. ?$file = "temp.txt";      
  2. $fp = fopen($file , 'w');      
  3. if(flock($fp , LOCK_EX)){      
  4.      fwrite($fp , "abcn");      
  5.      sleep(10);      
  6.      fwrite($fp , "123n");      
  7.     flock($fp , LOCK_UN);      
  8. }      
  9. fclose($fp); 

(2) b.php

  1. ?$file = "temp.txt";      
  2. $fp = fopen($file , 'r');      
  3. echo fread($fp , 100);      
  4. fclose($fp); 

运行 a.php 后,马上运行 b.php ,可以看到输出:

abc

等 a.php 运行完后运行 b.php ,可以看到输出:

abc

123

显然,当 a.php 写文件时数据太大,导致时间比较长时,这时 b.php 读取数据不完整

修改 b.php 为:

实例代码如下:

  1. ?$file = "temp.txt";      
  2. $fp = fopen($file , 'r');      
  3. if(flock($fp , LOCK_EX)){      
  4.     echo fread($fp , 100);      
  5.     flock($fp , LOCK_UN);      
  6. else{      
  7.     echo "Lock file failed…n";      
  8. }      
  9. fclose($fp);  

运行 a.php 后,马上运行 b.php ,可以发现 b.php 会等到 a.php 运行完成后(即 10 秒后)才显示:

abc
123

读取数据完整,但时间过长,他要等待写锁释放.修改 b.php 为:

实例代码如下:

  1. ?$file = "temp.txt";      
  2. $fp = fopen($file , 'r');      
  3. if(flock($fp , LOCK_SH | LOCK_NB)){      
  4.     echo fread($fp , 100);      
  5.     flock($fp , LOCK_UN);      
  6. else{      
  7.     echo "Lock file failed…n";      
  8. }      
  9. fclose($fp);  

运行 a.php 后,马上运行 b.php ,可以看到输出:

Lock file failed…

证明可以返回锁文件失败状态,而不是向上面一样要等很久.

结论:

建议作文件缓存时,选好相关的锁,不然可能导致读取数据不完整,或重复写入数据.file_get_contents 好像选择不了锁,不知道他默认用的什么锁,反正和不锁得到的输出一样,是不完整的数据.

我是要做文件缓存,所以只需要知道是否有写锁存在即可,有的话就查数据库就可以了.多次同时执行,虽然都写了100行,但是事务1和事务2的数据交错写入,这并不是我们想要的结果.我们要的是事务完整的执行,此时我们需要有个机制去保证在第一个事务执行完后再执行第二个.在PHP中,flock函数完成了这一使命.在事物1和事务2的循环前面都加上: flock($fp, LOCK_EX); 就能满足我们的需求,将两个事务串行.

当某一个事务执行完flock时,因为我们在这里添加的是LOCK_EX(独占锁定),所以所有对资源的操作都会被阻塞,只有当事务执行完成后,后面的事务才会执行.我们可以通过输出当前的时间的方法来确认这一点.

关于在尾部追加写入,在unix系统的早期版本中存在一个并发写入的问题,如果要在尾部追加,需要先lseek位置,再write.当多个进程同时操作时,会因为并发导致的覆盖写入的问题,即两个进程同时获取尾部的偏移后,先后执行write操作,后面的操作会将前面的操作覆盖.这个问题在后面以添加打开时的O_APPEND操作而得到解决,它将查找和写入操作变成了一个原子操作.

在PHP的fopen函数的实现中,如果我们使用a参数在文件的尾部追加内容,其调用open函数中oflag参数为 O_CREAT|O_APPEND,即我们使用追加操作不用担心并发追加写入的问题.

在PHP的session默认存储实现中也用到了flock文件锁,当session开始时就调用PS_READ_FUNC,且以O_CREAT | O_RDWR | O_BINARY 打开session数据文件,此时会调用flock加上写锁,如果此时有其它进程访问此文件(即同一用户再次发起对当前文件的请求),就会显示页面加载中,进程被阻塞了.加写锁其出发点是为了保证此次会话中对session的操作事务能完整的执行,防止其它进程的干扰,保证数据的一致性.如果一个页面没有session修改操作,可以尽早的调用session_write_close()释放锁.

文件锁是针对文件的锁,除了这种释义,还可以理解为用文件作为锁.在实际工作中,有时为确保单个进程的执行,我们会在程序执行前判断文件是否存在,如果不存在则创建一个空文件,在进程结束后删除这个空文件,如果存在,则不执行.

但是什么时候使用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写完并释放锁之后才进行读. 

波比源码 – 精品源码模版分享 | www.bobi11.com
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 本站源码并不保证全部能正常使用,仅供有技术基础的人学习研究,请谨慎下载
8. 如遇到加密压缩包,请使用WINRAR解压,如遇到无法解压的请联系管理员!

波比源码 » PHP flock文件锁详解介绍

156 评论

  1. aldactone 100mg sale cost valacyclovir buy fluconazole 200mg online cheap

  2. buy sildenafil 100mg pill careprost uk purchase methocarbamol pills

  3. order lamictal 200mg pill buy tretinoin gel order tretinoin gel sale

  4. order indocin 75mg pill lamisil pill buy trimox sale

  5. clonidine 0.1 mg drug antivert tablet order generic spiriva 9 mcg

  6. buy benicar 10mg pills diamox generic cost acetazolamide 250 mg

  7. order prograf 1mg for sale urso ca order ursodiol 150mg for sale

  8. order generic cialis 40mg cheap viagra order sildenafil 100mg sale

  9. furosemide for sale online buy lasix 100mg hydroxychloroquine 400mg sale

  10. order tadalafil 5mg generic oral tadalafil cheap sildenafil for sale

  11. buy temovate without prescription brand temovate cordarone 100mg generic

  12. lanoxin 250mg without prescription molnupiravir canada buy molnupiravir 200mg sale

  13. buy indomethacin generic flomax cheap purchase cenforce sale

  14. order doxycycline 100mg for sale medrol pills methylprednisolone 4mg without prescription

  15. Thank you for content. Area rugs and online home decor store. Hello Administ . Metropol Halı Karaca Halı Öztekin ve Selçuklu Halı Cami Halısı ve Cami Halıları Türkiye’nin En Büyük Cami Halısı Fabrikasıyız…

  16. Thank you great posting about essential oil. Hello Administ . Metropol Halı Karaca Halı Öztekin ve Selçuklu Halı Cami Halısı ve Cami Halıları Türkiye’nin En Büyük Cami Halısı Fabrikasıyız…

  17. buy uroxatral 10mg without prescription diltiazem buy online order diltiazem generic

  18. biltricide pills buy periactin purchase cyproheptadine online

  19. buy generic avanafil over the counter cheap avana 200mg order voltaren 50mg sale

  20. buy clindamycin without a prescription cheap fildena 100mg buy generic fildena online

  21. purchase digoxin without prescription molnunat brand oral molnunat

  22. order aristocort 4mg pills claritin order claritin canada

  23. topamax pills topiramate uk buy levofloxacin 500mg sale

  24. tadalafil 20mg for sale viagra for sale sildenafil 50mg for sale

  25. lamisil pills suprax 100mg us buy amoxicillin 500mg generic

  26. buy cheap generic fexofenadine fexofenadine ca buy amaryl online

  27. order praziquantel 600 mg generic oral periactin purchase periactin online cheap

  28. buy dexamethasone 0,5 mg online starlix 120 mg uk nateglinide 120mg brand

评论已关闭

Hi, 如果你对这款模板有疑问,可以跟我联系哦!

联系站长
赞助VIP 享更多特权,建议使用 QQ 登录
喜欢我嘛?喜欢就按“ctrl+D”收藏我吧!♡