PHP中文件锁

PHP中文件锁

文件锁的用途:

若一个人在写入一个文件,另外一个人同时也打个了这个文件进行写入文件。
这情况下,如果遇到一定的碰撞概率的话,不知道到底谁的操作为准。
因此,这个时候我们引入锁机制。
若用户A在写入或者读取这个文件的时候,将文件加上共享锁。我可以读,其他人也可以读。
但是,我如果这与的时候。我使用独占锁。这个文件归我了,你们都别动,除非我将文件锁进行释放。

注意:加上了文件锁后要注意释放

一、交叉写入

1、文件没有加锁

demo.php

header('content-type:text/html;charset=utf-8');
$filename = 'flock.txt';
$handle = fopen($filename,'a');

for($i=0;$i<1000000; $i++){
    fwrite($handle,'x');
}

demo_b.php

header('content-type:text/html;charset=utf-8');
$filename = 'flock.txt';
$handle = fopen($filename,'a');

for($i=0;$i<1000000; $i++){
    fwrite($handle,'b');
}

2、添加独占锁

demo.php

header('content-type:text/html;charset=utf-8');
$filename = 'flock.txt';
$handle = fopen($filename,'a');
flock($handle,LOCK_EX);
for($i=0;$i<1000000; $i++){
    fwrite($handle,'x');
}

demo_b.php

header('content-type:text/html;charset=utf-8');
$filename = 'flock.txt';
$handle = fopen($filename,'a');
flock($handle,LOCK_EX);
for($i=0;$i<1000000; $i++){
    fwrite($handle,'b');
}

二、关于阻塞

在PHP 5.3.2版本之前,锁会被 fclose() 释放(在脚本结束后会自动调用),现在需要手动解锁

锁方式说明
LOCK_SH 取得共享锁(读取的程序)
LOCK_EX 取得独占锁(写入的程序)
LOCK_UN 释放锁定 (无论共享或独占)
LOCK_NB 在flock()锁定时不阻塞 windows不支持

实例1:A使用独占锁写文件,B读取文件,阻塞

a.php

$file = 'test.txt';
$fp = fopen($file, 'w');

if(flock($fp, LOCK_EX)){            // 取得独占锁  
    fwrite($fp, "Hello World\r\n"); // 写入数据  
    sleep(10);                      // sleep 10秒,文件被锁定  
    fwrite($fp, "Hello PHP\r\n");   // 写入数据  
    flock($fp, LOCK_UN);            // 解锁  
}

fclose($fp);

b.php

$file = 'test.txt';
$fp = fopen($file, 'r');  

if(flock($fp, LOCK_SH)){ // 取得共享锁  
    while(!feof($fp)){  
        echo fread($fp, 100);  
    }  
    flock($fp, LOCK_UN);  
}

fclose($fp);

先执行a.php,然后执行b.php a取得独占锁,b只能等待,等a执行完解除锁定后才能执行b,阻塞

实例2:A,B都使用共享锁,不阻塞

a.php

$file = 'test.txt';
$fp = fopen($file, 'r');

if(flock($fp, LOCK_SH)){ // 取得共享锁  
    sleep(10);           // sleep 10秒  
    while(!feof($fp)){  
        echo fread($fp, 100);  
    }  
    flock($fp, LOCK_UN);  
}

fclose($fp);

b.php

$file = 'test.txt';  
$fp = fopen($file, 'r');  

if(flock($fp, LOCK_SH)){ // 取得共享锁  
    while(!feof($fp)){  
        echo fread($fp, 100);  
    }  
    flock($fp, LOCK_UN);  
}  

fclose($fp); 

先执行a.php,然后执行b.php

b不需要等待a执行完就能输出文件内容,非阻塞

实例3:A,B都使用独占锁写文件,阻塞

a.php

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

if(flock($fp, LOCK_EX)){            // 取得独占锁  
    fwrite($fp, "Hello World\r\n"); // 写入数据  
    sleep(10);                      // sleep 10秒,文件被锁定  
    fwrite($fp, "Hello PHP\r\n");   // 写入数据  
    flock($fp, LOCK_UN);            // 解锁  
}  

fclose($fp);

b.php

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

if(flock($fp, LOCK_EX)){                    // 取得独占锁  
    fwrite($fp, "How Are You\r\n");         // 写入数据  
    fwrite($fp, "Show Me The Money\r\n");   // 写入数据  
    flock($fp, LOCK_UN);                    // 解锁  
}  

fclose($fp);

先执行a.php,然后执行b.php

b需要等待a执行完,才能写入数据,阻塞

实例4:LOCK_NB 锁定时不阻塞,不等待

a.php

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

if(flock($fp, LOCK_EX)){            // 取得独占锁  
    fwrite($fp, "Hello World\r\n"); // 写入数据  
    sleep(10);                      // sleep 10秒,文件被锁定  
    fwrite($fp, "Hello PHP\r\n");   // 写入数据  
    flock($fp, LOCK_UN);            // 解锁  
}  

fclose($fp);

b.php

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

if(flock($fp, LOCK_EX|LOCK_NB)){            // 取得独占锁  
    fwrite($fp, "How Are You\r\n");         // 写入数据  
    fwrite($fp, "Show Me The Money\r\n");   // 写入数据  
    flock($fp, LOCK_UN);                    // 解锁  
}else{  
    echo 'file locked';
}

fclose($fp);

先执行a.php,然后执行b.php

b取不到独占锁,不需要等待a执行完,而是直接返回取不到锁提示,非阻塞

总结

使用共享锁LOCK_SH,如果是读取,不需要等待,但如果是写入,需要等待读取完成。

使用独占锁LOCK_EX,无论写入/读取都需要等待。

LOCK_UN,无论使用共享/读占锁,使用完后需要解锁。

LOCK_NB,当被锁定时,不阻塞,而是提示锁定。

posted @ 2023-11-11 10:01  杨国成  阅读(228)  评论(0编辑  收藏  举报