最近因為工作的需要在研究php,碰到了一個問題,我使用如下代碼鎖定一個文件句柄
[php]
<?php
$filename = "/tmp/lock.txt";
$fp = fopen($filename, "r+");
if (!$fp) {
die("open failed.");
}
if (flock($fp, LOCK_EX)) { // 進行排它型鎖定
sleep(20);
$count = (int)fgets($fp);
$count += 1;
fseek($fp, 0);
fwrite($fp, (string)$count);
fflush($fp); // flush output before releasing the lock
flock($fp, LOCK_UN); // 釋放鎖定
} else {
echo "Couldn't get the lock!";
}
fclose($fp);
?>
<?php
$filename = "/tmp/lock.txt";
$fp = fopen($filename, "r+");
if (!$fp) {
die("open failed.");
}
if (flock($fp, LOCK_EX)) { // 進行排它型鎖定
sleep(20);
$count = (int)fgets($fp);
$count += 1;
fseek($fp, 0);
fwrite($fp, (string)$count);
fflush($fp); // flush output before releasing the lock
flock($fp, LOCK_UN); // 釋放鎖定
} else {
echo "Couldn't get the lock!";
}
fclose($fp);
?>
訪問,然後在sleep的20秒內嘗試使用vi編輯/tmp/lock.txt,發現可以成功修改文件內容而不需要等待第一個腳本結束。經琢磨文檔,發現這裡有個概念叫"咨詢文件鎖定",就是說所有訪問程序必須使用同一方式鎖定才會生效, 否則它不會工作。
嘗試使用如下代碼在20秒內訪問:
[php]
<?php
$filename = "/tmp/lock.txt";
$fp = fopen($filename, "r+");
if (!$fp) {
die("open failed.");
}
if (flock($fp, LOCK_EX)) { // 進行排它型鎖定
$count = (int)fgets($fp);
echo $count;
$count += 1;
flock($fp, LOCK_UN); // 釋放鎖定
} else {
echo "Couldn't get the lock!";
}
fclose($fp);
?>
<?php
$filename = "/tmp/lock.txt";
$fp = fopen($filename, "r+");
if (!$fp) {
die("open failed.");
}
if (flock($fp, LOCK_EX)) { // 進行排它型鎖定
$count = (int)fgets($fp);
echo $count;
$count += 1;
flock($fp, LOCK_UN); // 釋放鎖定
} else {
echo "Couldn't get the lock!";
}
fclose($fp);
?>
發現阻塞成功(第二個腳本需要等待第一個腳本結束才能繼續運行)。
那麼,什麼叫同一種方式鎖定呢?
A組:
1.嘗試腳本1的flock參數修改為LOCK_SH,腳本2不變,試驗,發現阻塞依然成功;
2.嘗試腳本1和腳本2的flock參數都修改為LOCK_SH,發現腳本2會可以返回結果而不用等待腳本1執行結束;
B組:
1.嘗試將腳本2的fopen參數修改為"r",現象同A組;
C組:
1.嘗試將腳本2的flock參數修改為LOCK_SH,腳本1不變。