并发锁(二):共享锁和独占锁

简介: 并发锁(二):共享锁和独占锁

在上篇的文章中,我们了解了为什么需要锁,以及锁的应用场景。

那么,该怎么用锁来进行并发业务逻辑呢?

在php中,已经提供了关于锁的函数 flock

flock(file,lock,block)

参数

描述

file

必需。规定要锁定或释放的已打开的文件。

lock

必需。规定要使用哪种锁定类型。

可能的值:

  • LOCK_SH - 共享锁定(读取的程序)。允许其他进程访问该文件。
  • LOCK_EX - 独占锁定(写入的程序)。防止其他进程访问该文件。
  • LOCK_UN - 释放一个共享锁定或独占锁定
  • LOCK_NB - 锁定的情况下避免阻塞其他进程。

block

可选。若设置为 1,则当进行锁定时阻塞其他进程。

首先,我们要分清楚,锁有2种,共享锁,以及独占锁

共享锁

共享锁用于某个文件不会被写,或者不会被更新(也就是只读)的情况,加了共享锁的文件,只能再加共享锁,而不能加独占锁

例如:

$file = fopen('1.txt','r');
if (flock($file,LOCK_SH)){
    //读取一次文件的数据
    $data = fread($file,1);
    var_dump($data);
    echo "加锁成功\\n";
    //阻塞一次,方便运行另一个测试文件
    fread(STDIN,1);
    //文件指针重置
    fseek($file,0);
    //继续获取
    $data = fread($file,1);
    var_dump($data);
}

运行2次该代码,正常上锁并正常读取数据:

image.png

同样,如果在上了共享锁的情况,增加独占锁,则该进程会阻塞,直到共享锁释放:

<?php
$file = fopen('1.txt','r');
if (flock($file,LOCK_EX)){
    $data = fread($file,1);
    var_dump($data);
    echo "加锁成功";
    fread(STDIN,1);
}

image.png

需要所有的共享锁文件释放,才可加锁成功:

image.png

同理,如果是先加了独占锁,则共享锁会被阻塞,不做详细说明

注意事项

共享锁加上之后,虽然不能再加上独占锁进行独占写入,但是还是会被未加锁的进程影响,所以注意,当你确定某个文件是只读,或者说读取的时候不被写入影响时,关于操作这个文件的代码,都需要增加锁,不管是独占锁还是共享锁,否则数据还是会出现问题

例如:

当加好共享锁之后,运行这段代码:

<?php
$file = fopen('1.txt','r+');
fwrite($file,2,1);

数据将会出现变动:

image.png

独占锁

独占锁用于数据可能会被修改的文件,当一个进程加上独占锁之后,其他进程将不能增加独占锁和共享锁(将会阻塞)

测试代码:

<?php
$file = fopen('1.txt','r+');
if (flock($file,LOCK_EX)){
    echo "加锁成功\\n";
    //读取一次文件的数据
    $data = fread($file,11);
    var_dump($data);
    //读取一次文件的数据
    $time = time();
    //文件指针重置
    fseek($file,0,SEEK_SET );
    $data = fwrite($file,$time,strlen($time));
    //阻塞一次,方便运行另一个测试文件
    fread(STDIN,11);
    //文件指针重置
    fseek($file,0,SEEK_SET );
    //继续获取
    $data = fread($file,11);
    var_dump($data);
}

当进程1运行该代码时,进程2将会阻塞,无法加锁:

image.png

同样,共享锁也会出现一样的情况(不做测试)

注意事项

独占锁加上之后,虽然其他进程无法加共享锁以及独占锁,但是可以直接写入文件,同样会造成数据污染,所以注意,当你确定某个文件确定需要加锁时,关于操作这个文件的代码,都需要增加锁,不管是独占锁还是共享锁,否则数据还是会出现问题

<?php
$file = fopen('1.txt','r+');
$result = fwrite($file,'65555555');
var_dump($result);
var_dump(fread($file,11));

image.png

其他

非阻塞

通过在flock函数中的参数中增加LOCK_NB,可以避免阻塞,当不能加锁时会直接返回失败:

<?php
$file = fopen('1.txt','r+');
if (flock($file,LOCK\_EX|LOCK\_NB)){
    echo "加锁成功\\n";
}else{
    echo "加锁失败";
}

image.png

并发解决

还记得第一篇并发锁的文章吗?通过这个方式,就可以实现同一个文件在同一时间自有一个进程访问了

目录
相关文章
|
7月前
|
人工智能 数据挖掘 大数据
“龟速”到“光速”?算力如何加速 AI 应用进入“快车道”
阿里云将联合英特尔、蚂蚁数字科技专家,带来“云端进化论”特别直播。
218 11
|
NoSQL Java Redis
Redis Cluster:Too many Cluster redirections异常
  转载请注明出处哈:http://carlosfu.iteye.com/blog/2240426   一、现象:     我们的redis私有云,对外提供了redis-standalone, redis-sentinel, redis-cluster三种类型的redis服务。
4599 0
Redis Cluster:Too many Cluster redirections异常
|
10月前
|
存储 人工智能 程序员
一文彻底搞明白C语言的数组
本文详细介绍了C语言中的数组,包括定义、初始化(静态与动态)、存储方式、访问方法及常用操作,如遍历、修改元素和作为函数参数传递。数组是C语言中最基本的数据结构之一,掌握它对编程至关重要。下篇将介绍二维数组,敬请期待!
513 0
一文彻底搞明白C语言的数组
|
9月前
|
SQL 分布式计算 数据挖掘
《智能数据建设与治理 Dataphin》的最佳实践
本文介绍了使用Dataphin进行离线数仓搭建的实操教程,涵盖从创建数据板块到数据分析的完整流程。内容包括登录控制台、配置计算源、创建离线管道、生成SQL语句、运行任务及验证数据等步骤。通过详细的操作指南和截图,帮助用户快速上手Dataphin,体验其强大的数据治理能力。总结中提到教程存在部分陈旧问题,建议加深对产品逻辑的理解以更好地掌握工具使用。
459 1
|
12月前
|
人工智能 自然语言处理 搜索推荐
AI 赋能:开启内容生产效率革命的密钥》
在数字化时代,AI技术正成为提高内容生产效率的关键工具。本文探讨了AI在文章写作、文案创作、翻译、图像识别与生成及数据分析等方面的应用,分析了其提高效率的方式、带来的优势与挑战,并通过新闻媒体、营销、教育等行业案例,展望了AI在内容生产领域的未来。
521 3
编译QCefView+VS2019+QT5.15.2
本文介绍了如何编译QCefView项目,并在VS2019和Qt 5.15.2环境下集成,包括编译结果、要点、cmake部署Qt的方法和相关参考链接。
906 2
编译QCefView+VS2019+QT5.15.2
|
运维 监控 Java
怎样在Java中进行日志记录?
怎样在Java中进行日志记录?
|
存储 人工智能 安全
数据治理:强化数据安全与隐私保护的基石
在当今这个数字化时代,数据已成为推动社会进步和企业发展的核心驱动力。从个人消费习惯到企业运营策略,从政府决策支持到科研创新突破,数据无处不在,其价值不言而喻。然而,随着数据量的爆炸性增长和流通范围的扩大,数据安全与隐私保护问题也日益凸显,成为制约数据价值最大化利用的重要瓶颈。因此,构建完善的数据治理体系,特别是强化数据安全与隐私保护,成为了时代发展的必然要求。
1247 5
|
存储 定位技术 图形学
Blender插件:GLTF 2.0 导入/导出工具
Blender插件:GLTF 2.0 导入/导出工具
709 0
|
JavaScript 前端开发 开发者
【Vue2从入门到精通】超简单的vue2开发环境安装
Vue是一款非常流行的JavaScript框架,它可以帮助开发者轻松地构建交互式的Web应用程序。在本文中,我们将会讲解如何搭建Vue2的开发环境,让你可以快速开始开发自己的Vue应用程序。
1058 0
【Vue2从入门到精通】超简单的vue2开发环境安装