PHP檔案鎖用法詳解_PHP教程

來源:互聯網
上載者:User
PHP出現檔案鎖與mysql表鎖有大概想的用法,就是同一時間只能讓一個人操作,這樣就避免了同時有多個人操作同一檔案,這樣導致資料丟失的情況了,下面我來給大家介紹PHP檔案鎖用法。

PHP內建了檔案鎖函數:
bool flock ( int $handle , int $operation [, int &$wouldblock ] )
$handle 是開啟的檔案指標;
$operation 可以是
“LOCK_SH”,共用鎖定定;“LOCK_EX”,獨佔鎖定;“LOCK_UN”,釋放鎖定;“LOCK_NB”,防止flock鎖定時堵塞。
這裡主要說說“LOCK_EX”和“LOCK_NB”。

比如我們有兩個檔案,如下。


flocka.php

代碼如下 複製代碼

$file = 'temp.txt';
$fp = fopen($file,'a');

for($i = 0;$i < 5;$i++)
{
fwrite($fp, "11111111n");
sleep(1);
}

fclose($fp);

flockb.php

代碼如下 複製代碼
$file = 'temp.txt';
$fp = fopen($file,'a');

for($i = 0;$i < 5;$i++)
{
fwrite($fp, "22222222n");
}

fclose($fp);

先運行flocka.php,然後馬上運行flockb.php。
結果:
11111111
22222222
22222222
22222222
22222222
22222222
11111111
11111111
11111111
11111111
說明不加檔案鎖時,兩個檔案會同時對txt檔案進行寫入操作。
下面修改一下兩個php檔案的代碼。
flocka.php

代碼如下 複製代碼
$file = 'temp.txt';
$fp = fopen($file,'a');

if(flock($fp,LOCK_EX))
{
for($i = 0;$i < 5;$i++)
{
fwrite($fp, "11111111n");
sleep(1);
}
flock($fp,LOCK_UN);
}
fclose($fp);

flockb.php

代碼如下 複製代碼
$file = 'temp.txt';
$fp = fopen($file,'a');

if(flock($fp,LOCK_EX))
{
for($i = 0;$i < 5;$i++)
{
fwrite($fp, "22222222n");
}
flock($fp,LOCK_UN);
}

fclose($fp);

同樣先運行flocka.php,然後馬上運行flockb.php。
會發現在flocka.php運行結束前,flockb.php一直處於等待狀態,只有當flocka.php運行結束後,flockb.php才會繼續執行。
輸出結果:
11111111
11111111
11111111
11111111
11111111
22222222
22222222
22222222
22222222
22222222
另外,在執行flock時,檔案鎖會自動釋放。


還有一種辦法


如下代碼簡單類比了這種事務並髮狀態: process1.php

代碼如下 複製代碼
$num = 100;
$filename = "processdata.txt";

$fp = fopen($filename, "a");
for ($i = 0; $i < $num; $i++) {
fwrite($fp, "process1: " . $i . "rn");
usleep(100000);
}
fclose($fp);
?>

我們需要先執行第一個事務,在processdata.txt檔案中寫入這100行。

process2.php

代碼如下 複製代碼

$num = 100;
$filename = "processdata.txt";

$fp = fopen($filename, "a");
for ($i = 0; $i < $num; $i++) {
fwrite($fp, "process2: " . $i . "rn");
usleep(100000);
}
fclose($fp);
?>

第二個事務,繼續向processdata.txt檔案中寫入100行。

第二個事務,繼續向processdata.txt檔案中寫入100行。

多次同時執行,雖然都寫了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()釋放鎖。

檔案鎖是針對檔案的鎖,除了這種釋義,還可以理解為用檔案作為鎖。在實際工作中,有時為確保單個進程的執行,我們會在程式執行前判斷檔案是否存在,如果不存在則建立一個空檔案,在進程結束後刪除這個空檔案,如果存在,則不執行。

http://www.bkjia.com/PHPjc/628753.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/628753.htmlTechArticlePHP出現檔案鎖與mysql表鎖有大概想的用法,就是同一時間只能讓一個人操作,這樣就避免了同時有多個人操作同一檔案,這樣導致資料丟失的...

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.