php 文件锁

Posted 诚享人生

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了php 文件锁相关的知识,希望对你有一定的参考价值。

直接上码:

这里的文件锁:只是添加了一个 \'lock.lck\' 的文件,当多个客户端同时并发执行时,若存在这个文件,都无法执行,只有这个锁被删除之后才能执行,业务代码A只能同一时段一人执行。防止数据出错。

$lock =  \'lock.lck\';
while(true){
    if( file_exists($lock) ) {
        usleep(100);
    } else {
        touch($lock);//touch() 函数设置指定文件的访问和修改时间。
        
        //..........此处业务代码A........            
        }
        break;
    }
}
if(file_exists($lock)){
    $info .= "delete is  lock\\r\\n";
    unlink($lock);
}

 

以下为学习到的文件:

当多个客户端同时并发访问时,脚本的结果会出现不正确,这个问题需要使用锁机制来解决。
在我们这个网站中需要用到锁的地方就是高并发下定单时减少商品库存量时。这就要涉及到锁机制,在同一个段只允许一个人访问,防止数据数显错误!!
锁有两种:一种是mysql的表锁,另一个是php文件锁

文件锁:PHP锁定的是一个文件,所以要先有一个文件。

bool flock ( int handle, int operation [, int &wouldblock] );
flock() 操作的 handle 必须是一个已经打开的文件指针。operation 可以是以下值之一:

    1. 要取得共享锁定(读取程序),将 operation 设为 LOCK_SH(PHP 4.0.1 以前的版本设置为 1)
    2. 要取得独占锁定(写入程序),将 operation 设为 LOCK_EX(PHP 4.0.1 以前的版本中设置为 2)
    3. 要释放锁定(无论共享或独占),将 operation 设为 LOCK_UN(PHP 4.0.1 以前的版本中设置为 3)
    4. 如果你不希望 flock() 在锁定时堵塞,则给 operation 加上 LOCK_NB(PHP 4.0.1 以前的版本中设置为 4)

阻塞(等待)模式

<?php
$fp = fopen("lock.txt", "r");
if(flock($fp,LOCK_EX))
{
//..处理订单
flock($fp,LOCK_UN);
}
fclose($fp);
?>

非阻塞模式

<?php
$fp = fopen("lock.txt", "r");
if(flock($fp,LOCK_EX | LOCK_NB))
{
//..处理订单
flock($fp,LOCK_UN);
}
else
{
echo "系统繁忙,请稍后再试";
}

fclose($fp);
?>
class Order{
 
    /**
     * 阻塞模式(后面的进程会一直等待前面的进程执行完毕)
     */
    public function createOrder1(){
        $file = fopen(__DIR__.\'/lock.txt\',\'w+\');
        //加锁
        if(flock($file,LOCK_EX)){
            //TODO 执行业务代码
            flock($file,LOCK_UN);//解锁
        }
        //关闭文件
        fclose($file);
    }
 
    /**
     * 非阻塞模式(只要当前文件有锁存在,那么直接返回)
     */
    public function createOrder2(){
        $file = fopen(__DIR__.\'/lock.txt\',\'w+\');
        //加锁
        if(flock($file,LOCK_EX|LOCK_NB)){
            //TODO 执行业务代码
            flock($file,LOCK_UN);//解锁
        }else{
            //TODO 执行业务代码 返回系统繁忙等错误提示
        }
        //关闭文件
        fclose($file);
    }
}

读的时候: 
如果不想出现dirty数据,那么最好使用lock_sh共享锁。可以考虑以下三种情况: 
1. 如果读的时候没有加共享锁,那么其他程序要写的话(不管这个写是加锁还是不加锁)都会立即写成功。如果正好读了一半,然后被其他程序给写了,那么读的后一半就有可能跟前一半对不上(前一半是修改前的,后一半是修改后的) 
2. 如果读的时候加上了共享锁(因为只是读,没有必要使用排他锁),这个时候,其他程序开始写,这个写程序没有使用锁,那么写程序会直接修改这个文件,也会导致前面一样的问题 
3. 最理想的情况是,读的时候加锁(lock_sh),写的时候也进行加锁(lock_ex),这样写程序会等着读程序完成之后才进行操作,而不会出现贸然操作的情况 

写的时候: 
如果多个写程序不加锁同时对文件进行操作,那么最后的数据有可能一部分是a程序写的,一部分是b程序写的 
如果写的时候加锁了,这个时候有其他的程序来读,那么他会读到什么东西呢? 
1. 如果读程序没有申请共享锁,那么他会读到dirty的数据。比如写程序要写a,b,c三部分,写完a,这时候读读到的是a,继续写b,这时候读读到的是ab,然后写c,这时候读到的是abc. 
2. 如果读程序在之前申请了共享锁,那么读程序会等写程序将abc写完并释放锁之后才进行读

部分摘录:

https://www.cnblogs.com/tianjiale/p/9757206.html

https://www.cnblogs.com/chenwenbiao/archive/2011/08/01/2123905.html

https://www.cnblogs.com/zhouguowei/p/9708380.html

以上是关于php 文件锁的主要内容,如果未能解决你的问题,请参考以下文章

php代码片段: sendFile/videoStream/sendEmail/phpexcel/ffmpeg/zip

php 文件锁

PHP 之文件锁解决并发问题

php文件锁

php 文件锁

PHP中的锁文件