多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國(guó)內(nèi)最全I(xiàn)T社區(qū)平臺(tái) 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁(yè) > php開(kāi)源 > php教程 > PHP flock文件鎖詳解介紹

PHP flock文件鎖詳解介紹

來(lái)源:程序員人生   發(fā)布時(shí)間:2014-02-13 09:07:46 閱讀次數(shù):2702次

為了確保操作的有效性和完整性,可以通過(guò)鎖機(jī)制將并發(fā)狀態(tài)轉(zhuǎn)換成串行狀態(tài).作為鎖機(jī)制中的一種,PHP的文件鎖也是為了應(yīng)對(duì)資源競(jìng)爭(zhēng).假設(shè)一個(gè)應(yīng)用場(chǎng)景,在存在較大并發(fā)的情況下,通過(guò)fwrite向文件尾部多次有序的寫(xiě)入數(shù)據(jù),不加鎖的情況下會(huì)發(fā)生什么?多次有序的寫(xiě)入操作相當(dāng)于一個(gè)事務(wù),我們此時(shí)需要保證這個(gè)事務(wù)的完整性.

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

flock() 操作的 handle 必須是一個(gè)已經(jīng)打開(kāi)的文件指針.operation 可以是以下值之一:

1.要取得共享鎖定(讀取程序),將 operation 設(shè)為 LOCK_SH(PHP 4.0.1 以前的版本設(shè)置為 1)

2.要取得獨(dú)占鎖定(寫(xiě)入程序),將 operation 設(shè)為 LOCK_EX(PHP 4.0.1 以前的版本中設(shè)置為 2)

3.要釋放鎖定(無(wú)論共享或獨(dú)占),將 operation 設(shè)為 LOCK_UN(PHP 4.0.1 以前的版本中設(shè)置為 3)

4.如果你不希望 flock() 在鎖定時(shí)堵塞,則給 operation 加上 LOCK_NB(PHP 4.0.1 以前的版本中設(shè)置為 4)

建兩個(gè)文件

實(shí)例代碼如下:

(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); 

運(yùn)行 a.php 后,馬上運(yùn)行 b.php ,可以看到輸出:

abc

等 a.php 運(yùn)行完后運(yùn)行 b.php ,可以看到輸出:

abc

123

顯然,當(dāng) a.php 寫(xiě)文件時(shí)數(shù)據(jù)太大,導(dǎo)致時(shí)間比較長(zhǎng)時(shí),這時(shí) b.php 讀取數(shù)據(jù)不完整

修改 b.php 為:

實(shí)例代碼如下:

  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);  

運(yùn)行 a.php 后,馬上運(yùn)行 b.php ,可以發(fā)現(xiàn) b.php 會(huì)等到 a.php 運(yùn)行完成后(即 10 秒后)才顯示:

abc
123

讀取數(shù)據(jù)完整,但時(shí)間過(guò)長(zhǎng),他要等待寫(xiě)鎖釋放.修改 b.php 為:

實(shí)例代碼如下:

  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);  

運(yùn)行 a.php 后,馬上運(yùn)行 b.php ,可以看到輸出:

Lock file failed…

證明可以返回鎖文件失敗狀態(tài),而不是向上面一樣要等很久.

結(jié)論:

建議作文件緩存時(shí),選好相關(guān)的鎖,不然可能導(dǎo)致讀取數(shù)據(jù)不完整,或重復(fù)寫(xiě)入數(shù)據(jù).file_get_contents 好像選擇不了鎖,不知道他默認(rèn)用的什么鎖,反正和不鎖得到的輸出一樣,是不完整的數(shù)據(jù).

我是要做文件緩存,所以只需要知道是否有寫(xiě)鎖存在即可,有的話就查數(shù)據(jù)庫(kù)就可以了.多次同時(shí)執(zhí)行,雖然都寫(xiě)了100行,但是事務(wù)1和事務(wù)2的數(shù)據(jù)交錯(cuò)寫(xiě)入,這并不是我們想要的結(jié)果.我們要的是事務(wù)完整的執(zhí)行,此時(shí)我們需要有個(gè)機(jī)制去保證在第一個(gè)事務(wù)執(zhí)行完后再執(zhí)行第二個(gè).在PHP中,flock函數(shù)完成了這一使命.在事物1和事務(wù)2的循環(huán)前面都加上: flock($fp, LOCK_EX); 就能滿足我們的需求,將兩個(gè)事務(wù)串行.

當(dāng)某一個(gè)事務(wù)執(zhí)行完flock時(shí),因?yàn)槲覀冊(cè)谶@里添加的是LOCK_EX(獨(dú)占鎖定),所以所有對(duì)資源的操作都會(huì)被阻塞,只有當(dāng)事務(wù)執(zhí)行完成后,后面的事務(wù)才會(huì)執(zhí)行.我們可以通過(guò)輸出當(dāng)前的時(shí)間的方法來(lái)確認(rèn)這一點(diǎn).

關(guān)于在尾部追加寫(xiě)入,在unix系統(tǒng)的早期版本中存在一個(gè)并發(fā)寫(xiě)入的問(wèn)題,如果要在尾部追加,需要先lseek位置,再write.當(dāng)多個(gè)進(jìn)程同時(shí)操作時(shí),會(huì)因?yàn)椴l(fā)導(dǎo)致的覆蓋寫(xiě)入的問(wèn)題,即兩個(gè)進(jìn)程同時(shí)獲取尾部的偏移后,先后執(zhí)行write操作,后面的操作會(huì)將前面的操作覆蓋.這個(gè)問(wèn)題在后面以添加打開(kāi)時(shí)的O_APPEND操作而得到解決,它將查找和寫(xiě)入操作變成了一個(gè)原子操作.

在PHP的fopen函數(shù)的實(shí)現(xiàn)中,如果我們使用a參數(shù)在文件的尾部追加內(nèi)容,其調(diào)用open函數(shù)中oflag參數(shù)為 O_CREAT|O_APPEND,即我們使用追加操作不用擔(dān)心并發(fā)追加寫(xiě)入的問(wèn)題.

在PHP的session默認(rèn)存儲(chǔ)實(shí)現(xiàn)中也用到了flock文件鎖,當(dāng)session開(kāi)始時(shí)就調(diào)用PS_READ_FUNC,且以O(shè)_CREAT | O_RDWR | O_BINARY 打開(kāi)session數(shù)據(jù)文件,此時(shí)會(huì)調(diào)用flock加上寫(xiě)鎖,如果此時(shí)有其它進(jìn)程訪問(wèn)此文件(即同一用戶再次發(fā)起對(duì)當(dāng)前文件的請(qǐng)求),就會(huì)顯示頁(yè)面加載中,進(jìn)程被阻塞了.加寫(xiě)鎖其出發(fā)點(diǎn)是為了保證此次會(huì)話中對(duì)session的操作事務(wù)能完整的執(zhí)行,防止其它進(jìn)程的干擾,保證數(shù)據(jù)的一致性.如果一個(gè)頁(yè)面沒(méi)有session修改操作,可以盡早的調(diào)用session_write_close()釋放鎖.

文件鎖是針對(duì)文件的鎖,除了這種釋義,還可以理解為用文件作為鎖.在實(shí)際工作中,有時(shí)為確保單個(gè)進(jìn)程的執(zhí)行,我們會(huì)在程序執(zhí)行前判斷文件是否存在,如果不存在則創(chuàng)建一個(gè)空文件,在進(jìn)程結(jié)束后刪除這個(gè)空文件,如果存在,則不執(zhí)行.

但是什么時(shí)候使用lock_ex什么時(shí)候使用lock_sh呢?

讀的時(shí)候:

如果不想出現(xiàn)dirty數(shù)據(jù),那么最好使用lock_sh共享鎖.可以考慮以下三種情況: 

1. 如果讀的時(shí)候沒(méi)有加共享鎖,那么其他程序要寫(xiě)的話(不管這個(gè)寫(xiě)是加鎖還是不加鎖)都會(huì)立即寫(xiě)成功.如果正好讀了一半,然后被其他程序給寫(xiě)了,那么讀的后一半就有可能跟前一半對(duì)不上(前一半是修改前的,后一半是修改后的) 

2. 如果讀的時(shí)候加上了共享鎖(因?yàn)橹皇亲x,沒(méi)有必要使用排他鎖),這個(gè)時(shí)候,其他程序開(kāi)始寫(xiě),這個(gè)寫(xiě)程序沒(méi)有使用鎖,那么寫(xiě)程序會(huì)直接修改這個(gè)文件,也會(huì)導(dǎo)致前面一樣的問(wèn)題 

3. 最理想的情況是,讀的時(shí)候加鎖(lock_sh),寫(xiě)的時(shí)候也進(jìn)行加鎖(lock_ex),這樣寫(xiě)程序會(huì)等著讀程序完成之后才進(jìn)行操作,而不會(huì)出現(xiàn)貿(mào)然操作的情況

寫(xiě)的時(shí)候:

如果多個(gè)寫(xiě)程序不加鎖同時(shí)對(duì)文件進(jìn)行操作,那么最后的數(shù)據(jù)有可能一部分是a程序?qū)懙?一部分是b程序?qū)懙摹H绻麑?xiě)的時(shí)候加鎖了,這個(gè)時(shí)候有其他的程序來(lái)讀,那么他會(huì)讀到什么東西呢? 

1. 如果讀程序沒(méi)有申請(qǐng)共享鎖,那么他會(huì)讀到dirty的數(shù)據(jù).比如寫(xiě)程序要寫(xiě)a,b,c三部分,寫(xiě)完a,這時(shí)候讀讀到的是a,繼續(xù)寫(xiě)b,這時(shí)候讀讀到的是ab,然后寫(xiě)c,這時(shí)候讀到的是abc. 

2. 如果讀程序在之前申請(qǐng)了共享鎖,那么讀程序會(huì)等寫(xiě)程序?qū)bc寫(xiě)完并釋放鎖之后才進(jìn)行讀. 

生活不易,碼農(nóng)辛苦
如果您覺(jué)得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 精品亚洲在线 | 亚洲精品国产经典一区二区 | 亚洲欧美在线播放 | 久久亚洲精品中文字幕三区 | 欧美熟妇下面毛毛黑森林 | 叼嘿视频在线观看免费 | 中文字幕成人在线观看 | 求免费黄色网址 | 国产日韩视频在线观看 | 国产免费叼嘿网站免费 | 日本激情啪啪 | 图片区小说区激情区偷拍区 | 亚洲一逼 | 亚洲一区二区三区深夜天堂 | 伊人网站在线 | www.亚洲天堂网 | 欧美一级欧美一级高清 | 欧美一级毛级毛片 | 亚洲天码中字 | 国产一区二区三区精品久久呦 | 亚洲天堂2018av | 国产日产欧美精品一区二区三区 | 欧美一区二区在线免费观看 | 伊人网在线播放 | 无国产精品白浆免费视 | bt 自拍 另类 综合 欧美 | 日本xxxxxbbbbb精品 | 亚洲线精品久久一区二区三区 | 在线亚洲v日韩v | 欧美一级爆毛片 | 欧美a毛片| 女人一级特纯黄大片色 | 成人欧美精品久久久久影院 | 亚洲欧美日韩中文综合在线不卡 | 欧美日韩小说 | 亚洲黄色免费网址 | 91成人午夜精品福利院在线观看 | 精品国产福利在线观看网址2022 | 一区二区三区精品国产欧美 | 国产不卡视频一区二区在线观看 | 国产精品99爱免费视频 |