2012-08-05 42 views
7

我看到一羣使用人是這樣的:PHP的羊羣和FREAD和fwrite

if (!$fp = fopen($file_name, 'wb')) 
{ 
    return FALSE; 
} 

if (flock($fp, LOCK_EX)) 
{ 
    fwrite($fp, serialize($data)); 
    flock($fp, LOCK_UN); 
} 

而且這樣的:

if (!$fp = @fopen($file_name, 'rb')) 
{ 
    return FALSE; 
} 

flock($fp, LOCK_SH); 

$data = ''; 

if (filesize($file_name) > 0) 
{ 
    $data = unserialize(fread($fp, filesize($file_name))); 
} 

但是是不是有機會他人將編輯的文件fopen致電和flock致電?和fread


編輯同一個問題:
解釋,爲什麼我問這個......我立足我的問題上的代碼here,在MySQL緩存的情況下,有什麼能夠阻止20人從所有能夠同時訪問該文件,如果他們都能進入fopen和flock之間?

是代碼萬無一失嗎?

回答

6

在評論解釋你問:

是不是有機會,有人否則會在fopen調用和flock調用之間編輯文件?和fread相同的問題

是的,不,也許。簡短回答:假設「是」並謹慎行事。

是的,因爲基於傳統flock()的鎖定僅僅是建議,所以其他進程(或甚至相同的進程)可以自由地忽略鎖。在實踐中,這不是問題,因爲行爲良好的客戶端代碼使用flock() - 直到獲得LOCK_SH纔會讀取,而且除非獲得了應用程序上的LOCK_EX,否則不會寫入,特定的文件。

不,在PHP的實現羊羣()可能對某些操作系統強制性,每documentation,這可能也需要從文件系統(例如,與Linux下mand選項)的支持。所以,其他進程不能忽視這些鎖。

也許,PHP 5中的streams子系統實現了一些超出操作系統提供的locking bookkeeping。例如,這可能會阻止同一過程(而不是另一個過程)忽視其自己的其他諮詢鎖。行爲might surprise一些。即便如此,這種鎖定在不相關的過程之間也不是強制性的。對於可移植性,只需假定最弱的語義(上面的「是」)並將flock()限制在事先選擇的特定於應用程序的鎖文件上的良好行爲代碼。

+0

如果該緩存僅由該特定腳本使用,則不會發生任何情況。如果有人將文件從shell中刪除 - 確實會發生不好的事情。 – favoretti 2012-08-05 20:59:56

+0

是的,但正如另一條評論所述,LOCK_EX並不是像某種方式強迫fread一樣「不會返回」。 – pilcrow 2012-08-05 21:30:43

+0

如果您閱讀了PHP站點上的評論,但實際上確實如此,儘管鎖定是建議性的。也就是說,強制鎖定,例如,Linux只能在明確支持它的文件系統上進行工作,並按照這種方式進行安裝。 – favoretti 2012-08-05 21:35:02

2

第一個片段是非常簡單的,如果你不能鎖定文件,你就不會寫。如果其他人編輯了fopen()flock()之間的文件,您的文件句柄將指向最新的版本,因爲fopen()綁定到流,而不是「快照」。

第二個例子不能保證能正常工作,因爲flock()的返回值沒有被檢查,所以如果你還沒有獲得這個鎖,那麼隨後的代碼將被執行。

[編輯]刪除語句讀鎖不要緊,它實際上,如下:)

+0

我基於我的問題代碼[** here,**](http://www.jongales.com/blog/2009/02/18/simple-file-based-php-cache-class /)在mysql緩存的情況下,在這種情況下,基於該類中的代碼,什麼能阻止20個人同時訪問該文件? – qwertymk 2012-08-05 20:38:09

+0

對於閱讀 - 沒有什麼,這很可能是你想要的,併發緩存讀訪問,而不是獨佔。對於編寫,確切地說,獲得的鎖將阻止其他人寫入緩存。那些代碼完全困擾你的是什麼? – favoretti 2012-08-05 20:41:14

+0

我想一個小問題,如果100,000個人都嘗試設置相同的緩存文件,並且在fopen和flock之間調用20,000個,那麼將會有19,999個不需要的fwrites,其中一些人也會做檢查,看看緩存是新鮮的,並且會錯過它獲取的新文件時間。這甚至是一個問題嗎? – qwertymk 2012-08-05 20:45:13