码农编程阁-全国最大的中文编程交流平台

 找回密码
 立即注册
查看: 116|回复: 0

[文字教程] PHP 利用文件锁处理高并发

[复制链接]
回帖奖励 1 金币 回复本帖可获得 1 金币奖励! 每人限 1 次
  • TA的每日心情
    擦汗
    2025-3-10 11:56
  • 签到天数: 95 天

    连续签到: 1 天

    [LV.6]常住居民II

    170

    主题

    902

    帖子

    2万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    26745
    发表于 2021-3-5 19:47:40 | 显示全部楼层 |阅读模式

    利用flock()函数对文件进行加锁(排它锁),实现并发按序进行。

      flock(file,lock,block)有三个参数。

      file:已经打开的文件

      lock:锁的类型

        LOCK_SH:共享锁(读锁)

        LOCK_EX:独占锁定(排它锁,写锁)

        LOCK_UN:解锁

        LOCK_NB:如果希望在文件锁定时阻塞进程,那么需要加上该参数

      block:设置为true的时候,锁定文件时,会阻止其他进程

      下面是一个demo:


    1. class Order{

    2.     /**
    3.      * 阻塞模式(后面的进程会一直等待前面的进程执行完毕)
    4.      */
    5.     public function createOrder1(){
    6.         $file = fopen(__DIR__.'/lock.txt','w+');
    7.         //加锁
    8.         if(flock($file,LOCK_EX)){
    9.             //TODO 执行业务代码
    10.             flock($file,LOCK_UN);//解锁
    11.         }
    12.         //关闭文件
    13.         fclose($file);
    14.     }

    15.     /**
    16.      * 非阻塞模式(只要当前文件有锁存在,那么直接返回)
    17.      */
    18.     public function createOrder2(){
    19.         $file = fopen(__DIR__.'/lock.txt','w+');
    20.         //加锁
    21.         if(flock($file,LOCK_EX|LOCK_NB)){
    22.             //TODO 执行业务代码
    23.             flock($file,LOCK_UN);//解锁
    24.         }else{
    25.             //TODO 执行业务代码 返回系统繁忙等错误提示
    26.         }
    27.         //关闭文件
    28.         fclose($file);
    29.     }
    30. }
    复制代码

    提示:在执行fclose()的时候文件会自动解锁,所以可以省略解锁的代码。


    demo:

    1. 【一】.阻塞模式:(如果其他进程已经加锁文件,当前进程会一直等其他进程解锁文件后继续执行)
    2. <?php
    3. //连接数据库
    4. $con=mysqli_connect("192.168.2.186","root","root","test");
    5. //查询商品数量是否大于0,大于0才能下单,并减少库存
    6. $fp = fopen("lock.txt", "r");
    7. //加锁
    8. if(flock($fp,LOCK_EX))
    9. {
    10.         $res=mysqli_fetch_assoc(mysqli_query($con,'SELECT total FROM shop WHERE id=1 LIMIT 1'));
    11.         if($res['total']>0){mysqli_query($con,'UPDATE shop SET total=total-1  WHERE id=1');}
    12.         //执行完成解锁
    13.         flock($fp,LOCK_UN);
    14. }
    15. //关闭文件
    16. fclose($fp);
    17. unset($res);
    18. mysqli_close($con);
    19. ?>
    20. 这种情况若是其他进程已经加锁文件,那么所有进程都会等他执行完并解锁文件后才会执行

    21. 【二】.非阻塞模式:(如果其他进程已经加锁文件,当前进程不会等其他进程解锁文件,而是走else)<?php
    22. //连接数据库
    23. $con=mysqli_connect("192.168.2.186","root","root","test");

    24. //查询商品数量是否大于0,大于0才能下单,并减少库存

    25. $fp = fopen("lock.txt", "r");
    26. //加锁
    27. if(flock($fp,LOCK_EX | LOCK_NB))
    28. {
    29.         $res=mysqli_fetch_assoc(mysqli_query($con,'SELECT total FROM shop WHERE id=1 LIMIT 1'));
    30.         if($res['total']>0){mysqli_query($con,'UPDATE shop SET total=total-1  WHERE id=1');}
    31.         //执行完成解锁
    32.         flock($fp,LOCK_UN);
    33. }else{
    34.   echo "locked file failed\n";
    35. }
    36. unset($res);
    37. mysqli_close($con);
    38. ?>
    39. 这种情况就会直接走else返回提示信息
    复制代码



    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|码农编程阁-全国最大的中文编程交流平台

    GMT+8, 2025-4-29 21:23 , Processed in 0.133802 second(s), 24 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.

    快速回复 返回顶部 返回列表