redis系列:分布式锁

Redis的分布式锁详解 3)为了有效解决既保证锁完全有效性 和 性能高效问题:antirez又提出了“延迟重启”的概念,redis同步到磁盘方式保持默认的每秒1次,在redis崩溃单机后(无论是一个还是所有),先不立即重启它,而是等待TTL时间后再重启,这样的话,这个节点在重启前所参与的锁都会过期,它在重启后就不会对现有的锁造成影响,缺点是在TTL时间内服务相当于暂停状态;redisson在获取锁之后,会维护一个看门狗线程,在每一个锁设置的过期时间的1/3处,如果线程还没执行完任务,则不断延长锁的有效期。... 阅读详情

1 介绍

这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁。会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁。

本篇文章会将分布式锁的实现分为两部分,一个是单机环境,另一个是集群环境下的Redis锁实现。在介绍分布式锁的实现之前,先来了解下分布式锁的一些信息。

2 分布式锁

2.1 什么是分布式锁?

分布式锁是控制分布式系统或不同系统之间共同访问共享资源的一种锁实现,如果不同的系统或同一个系统的不同主机之间共享了某个资源时,往往需要互斥来防止彼此干扰来保证一致性。

2.2 分布式锁需要具备哪些条件

互斥性:在任意一个时刻,只有一个客户端持有锁。

无死锁:即便持有锁的客户端崩溃或者其他意外事件,锁仍然可以被获取。

容错:只要大部分Redis节点都活着,客户端就可以获取和释放锁

2.4 分布式锁的实现有哪些?

数据库

Memcached(add命令)

Redis(setnx命令)

Zookeeper(临时节点)

等等

3 单机Redis的分布式锁

3.1 准备工作

3.1.1 定义常量类

publicclassLockConstants{publicstaticfinalString OK ="OK";/** NX|XX, NX -- Only set the key if it does not already exist. XX -- Only set the key if it already exist. **/publicstaticfinalString NOT_EXIST ="NX";publicstaticfinalString EXIST ="XX";/** expx EX|PX, expire time units: EX = seconds; PX = milliseconds **/publicstaticfinalString SECONDS ="EX";publicstaticfinalString MILLISECONDS ="PX";privateLockConstants(){}}复制代码

3.1.2 定义锁的抽象类

抽象类RedisLock实现java.util.concurrent包下的Lock接口,然后对一些方法提供默认实现,子类只需实现lock方法和unlock方法即可。代码如下

publicabstractclassRedisLockimplementsLock{protectedJedis jedis;protectedString lockKey;publicRedisLock(Jedis jedis,String lockKey){this(jedis, lockKey);    }publicvoidsleepBySencond(intsencond){try{            Thread.sleep(sencond*1000);        }catch(InterruptedException e) {            e.printStackTrace();        }    }@OverridepublicvoidlockInterruptibly(){}@OverridepublicConditionnewCondition(){returnnull;    }@OverridepublicbooleantryLock(){returnfalse;    }@OverridepublicbooleantryLock(longtime, TimeUnit unit){returnfalse;    }}复制代码

3.2 最基础的版本1

先来一个最基础的版本,代码如下

publicclassLockCase1extendsRedisLock{publicLockCase1(Jedis jedis, String name){super(jedis, name);    }@Overridepublicvoidlock(){while(true){            String result = jedis.set(lockKey,"value", NOT_EXIST);if(OK.equals(result)){                System.out.println(Thread.currentThread().getId()+"加锁成功!");break;            }        }    }@Overridepublicvoidunlock(){        jedis.del(lockKey);    }}复制代码

LockCase1类提供了lock和unlock方法。

其中lock方法也就是在reids客户端执行如下命令

SET lockKey value NX复制代码

而unlock方法就是调用DEL命令将键删除。

好了,方法介绍完了。现在来想想这其中会有什么问题?

假设有两个客户端A和B,A获取到分布式的锁。A执行了一会,突然A所在的服务器断电了(或者其他什么的),也就是客户端A挂了。这时出现一个问题,这个锁一直存在,且不会被释放,其他客户端永远获取不到锁。如下示意图

13467292-8e94d8215ae0b6fa.png

>need-to-insert-img

可以通过设置过期时间来解决这个问题

3.3 版本2-设置锁的过期时间

publicvoidlock(){while(true){        String result = jedis.set(lockKey,"value", NOT_EXIST,SECONDS,30);if(OK.equals(result)){            System.out.println(Thread.currentThread().getId()+"加锁成功!");break;        }    }}复制代码

类似的Redis命令如下

SET lockKey value NX EX 30复制代码

注:要保证设置过期时间和设置锁具有原子性

这时又出现一个问题,问题出现的步骤如下

客户端A获取锁成功,过期时间30秒。

客户端A在某个操作上阻塞了50秒。

30秒时间到了,锁自动释放了。

客户端B获取到了对应同一个资源的锁。

客户端A从阻塞中恢复过来,释放掉了客户端B持有的锁。

示意图如下

13467292-e53277beccc8c80f.png

>need-to-insert-img

这时会有两个问题

过期时间如何保证大于业务执行时间?

如何保证锁不会被误删除?

先来解决如何保证锁不会被误删除这个问题。

这个问题可以通过设置value为当前客户端生成的一个随机字符串,且保证在足够长的一段时间内在所有客户端的所有获取锁的请求中都是唯一的。

版本2的完整代码:Github地址

3.4 版本3-设置锁的value

抽象类RedisLock增加lockValue字段,lockValue字段的默认值为UUID随机值假设当前线程ID。

public abstract class RedisLock implements Lock {    //...    protected String lockValue;    public RedisLock(Jedis jedis,String lockKey) {        this(jedis, lockKey, UUID.randomUUID().toString()+Thread.currentThread().getId());    }    public RedisLock(Jedis jedis, String lockKey, String lockValue) {        this.jedis = jedis;        this.lockKey = lockKey;        this.lockValue = lockValue;    }    //...}复制代码

加锁代码

public voidlock() {while(true){        String result = jedis.set(lockKey, lockValue, NOT_EXIST,SECONDS,30);if(OK.equals(result)){            System.out.println(Thread.currentThread().getId()+"加锁成功!");break;        }    }}复制代码

解锁代码

public voidunlock() {    String lockValue = jedis.get(lockKey);if(lockValue.equals(lockValue)){        jedis.del(lockKey);    }}复制代码

这时看看加锁代码,好像没有什么问题啊。

再来看看解锁的代码,这里的解锁操作包含三步操作:获取值、判断和删除锁。这时你有没有想到在多线程环境下的i++操作?

3.4.1 i++问题

i++操作也可分为三个步骤:读i的值,进行i+1,设置i的值。

如果两个线程同时对i进行i++操作,会出现如下情况

i设置值为0

线程A读到i的值为0

线程B也读到i的值为0

线程A执行了+1操作,将结果值1写入到内存

线程B执行了+1操作,将结果值1写入到内存

此时i进行了两次i++操作,但是结果却为1

在多线程环境下有什么方式可以避免这类情况发生?

解决方式有很多种,例如用AtomicInteger、CAS、synchronized等等。

这些解决方式的目的都是要确保i++操作的原子性。那么回过头来看看解锁,同理我们也是要确保解锁的原子性。我们可以利用Redis的lua脚本来实现解锁操作的原子性。

版本3的完整代码:Github地址

3.5 版本4-具有原子性的释放锁

lua脚本内容如下

ifredis.call("get",KEYS[1]) == ARGV[1]thenreturnredis.call("del",KEYS[1])elsereturn0end复制代码

这段Lua脚本在执行的时候要把的lockValue作为ARGV[1]的值传进去,把lockKey作为KEYS[1]的值传进去。现在来看看解锁的java代码

public voidunlock() {    // 使用lua脚本进行原子删除操作    String checkAndDelScript ="if redis.call('get', KEYS[1]) == ARGV[1] then "+"return redis.call('del', KEYS[1]) "+"else "+"return 0 "+"end";    jedis.eval(checkAndDelScript, 1, lockKey, lockValue);}复制代码

好了,解锁操作也确保了原子性了,那么是不是单机Redis环境的分布式锁到此就完成了?

别忘了版本2-设置锁的过期时间还有一个,过期时间如何保证大于业务执行时间问题没有解决。

版本4的完整代码:Github地址

3.6 版本5-确保过期时间大于业务执行时间

抽象类RedisLock增加一个boolean类型的属性isOpenExpirationRenewal,用来标识是否开启定时刷新过期时间。

在增加一个scheduleExpirationRenewal方法用于开启刷新过期时间的线程。

public abstract class RedisLock implements Lock {//...    protected volatile boolean isOpenExpirationRenewal =true;    /**    * 开启定时刷新    */    protected voidscheduleExpirationRenewal(){        Thread renewalThread = new Thread(new ExpirationRenewal());        renewalThread.start();    }    /**    * 刷新key的过期时间    */    private class ExpirationRenewal implements Runnable{        @Override        public voidrun() {while(isOpenExpirationRenewal){                System.out.println("执行延迟失效时间中...");                String checkAndExpireScript ="if redis.call('get', KEYS[1]) == ARGV[1] then "+"return redis.call('expire',KEYS[1],ARGV[2]) "+"else "+"return 0 end";                jedis.eval(checkAndExpireScript, 1, lockKey, lockValue,"30");                //休眠10秒                sleepBySencond(10);            }        }    }}复制代码

加锁代码在获取锁成功后将isOpenExpirationRenewal置为true,并且调用scheduleExpirationRenewal方法,开启刷新过期时间的线程。

publicvoidlock(){while(true) {        String result = jedis.set(lockKey, lockValue, NOT_EXIST, SECONDS,30);if(OK.equals(result)) {            System.out.println("线程id:"+Thread.currentThread().getId() +"加锁成功!时间:"+LocalTime.now());//开启定时刷新过期时间isOpenExpirationRenewal =true;            scheduleExpirationRenewal();break;        }        System.out.println("线程id:"+Thread.currentThread().getId() +"获取锁失败,休眠10秒!时间:"+LocalTime.now());//休眠10秒sleepBySencond(10);    }}复制代码

解锁代码增加一行代码,将isOpenExpirationRenewal属性置为false,停止刷新过期时间的线程轮询。

publicvoidunlock(){//...isOpenExpirationRenewal =false;}复制代码

版本5的完整代码:Github地址

3.7 测试

测试代码如下

publicvoidtestLockCase5(){//定义线程池ThreadPoolExecutor pool =newThreadPoolExecutor(0,10,1, TimeUnit.SECONDS,newSynchronousQueue<>());//添加10个线程获取锁for(inti =0; i <10; i++) {        pool.submit(() -> {try{                Jedis jedis =newJedis("localhost");                LockCase5 lock =newLockCase5(jedis, lockName);                lock.lock();//模拟业务执行15秒lock.sleepBySencond(15);                lock.unlock();            }catch(Exception e){                e.printStackTrace();            }        });    }//当线程池中的线程数为0时,退出while(pool.getPoolSize() !=0) {}}复制代码

测试结果

13467292-79d8def35d8347e2

或许到这里基于单机Redis环境的分布式就介绍完了。但是使用java的同学有没有发现一个锁的重要特性

那就是锁的重入,那么分布式锁的重入该如何实现呢?这里就留一个坑了

4 集群Redis的分布式锁

在Redis的分布式环境中,Redis 的作者提供了RedLock 的算法来实现一个分布式锁。

4.1 加锁

RedLock算法加锁步骤如下

获取当前Unix时间,以毫秒为单位。

依次尝试从N个实例,使用相同的key和随机值获取锁。在步骤2,当向Redis设置锁时,客户端应该设置一个网络连接和响应超时时间,这个超时时间应该小于锁的失效时间。例如你的锁自动失效时间为10秒,则超时时间应该在5-50毫秒之间。这样可以避免服务器端Redis已经挂掉的情况下,客户端还在死死地等待响应结果。如果服务器端没有在规定时间内响应,客户端应该尽快尝试另外一个Redis实例。

客户端使用当前时间减去开始获取锁时间(步骤1记录的时间)就得到获取锁使用的时间。当且仅当从大多数(这里是3个节点)的Redis节点都取到锁,并且使用的时间小于锁失效时间时,锁才算获取成功。

如果取到了锁,key的真正有效时间等于有效时间减去获取锁所使用的时间(步骤3计算的结果)。

如果因为某些原因,获取锁失败(没有在至少N/2+1个Redis实例取到锁或者取锁时间已经超过了有效时间),客户端应该在所有的Redis实例上进行解锁(即便某些Redis实例根本就没有加锁成功)。

4.2 解锁

向所有的Redis实例发送释放锁命令即可,不用关心之前有没有从Redis实例成功获取到锁.

关于RedLock算法,还有一个小插曲,就是Martin Kleppmann 和 RedLock 作者 antirez的对RedLock算法的互怼。 官网原话如下

Martin Kleppmannanalyzed Redlock here. I disagree with the analysis and postedmy reply to his analysis here.

更多关于RedLock算法这里就不在说明,有兴趣的可以到官网阅读相关文章。

5 总结

这篇文章讲述了一个基于Redis的分布式锁的编写过程及解决问题的思路,但是本篇文章实现的分布式锁并不适合用于生产环境。java环境有Redisson可用于生产环境,但是分布式锁还是Zookeeper会比较好一些

Java高架构师、分布式架构、高可扩展、高性能、高并发、性能优化、Spring boot、Redis、ActiveMQ、Nginx、Mycat、Netty、Jvm大型分布式项目实战学习架构师视频免费学习加群:835638062 点击链接加入群聊【Java高级架构】:https://jq.qq.com/?_wv=1027&k=5S3kL3v

从零构建OpenBMC风扇控制:基于phosphor-pid-control的实战配置指南 本文详细介绍了如何从零开始构建OpenBMC风扇控制系统,基于phosphor-pid-control框架实现风扇自动调速。通过解析PID算法配置、传感器定义及控制区域设置,提供工业级散热解决方案,帮助开发者优化服务器能效与可靠性。 阅读详情

相关推荐

grafana 配置页面告警

Rate 下拉选择也可,保持默认也可。By label 选择一个比如选择filename。配置无数据或者错误数据的时候如何处理,这里选择 Normal (表示当做正常不会告警)单机 node_name 标签,选择一个主机,选好后单机 Show logs。单机 New floder,如果之前配置过,也可以选择。单机 Save contact point 保存即可。会跳出如下对话框(如果没有跳出就自己单机选择下)完成后会自动生成如下图,告警规则部分就配置好了。选择告警接收方式(这里选择企业微信 WeCon)

weixin_40548182的博客 3254

Redis setnx和set(key,value,nxxx,expx,time)

redis中setnx不支持设置过期时间,做分布式锁时 要想避免某一客户端中断导致死锁 ,需设置lock过期时间,在高并发时 setnx与 expire 不能实现原子操作,如果要用,得在程序代码上显示的加锁 。 我是用set(key,value,nxxx,expx,time)时,判断 set(key,value,nxxx,expx,time).equals(“OK”)作为设置条件,但是发现程序会出...

别抢我蓝buff 1万+

Labview及NI-USRP驱动安装教程

软件下载 安装使用的LabVIEW2018及NI-USRP驱动程序已上传,下载地址: 天翼云盘链接 (访问码:oc33) 百度网盘链接 (提取码:88mi) (注:天翼云盘下载不限速) LabVIEW2018安装步骤 右键软件压缩包选择解压至LabVIEW2018 选中文件,鼠标右击选择以管理员身份打开2018LV-WinChn.exe文件。 点击确定。 点击Unzip解压。 点击确定。 点击下一步。 填写任意信息后,点击下一步。 点击下一步。 点击浏览更改安装路径建议安装到除C盘以

dadapongi6的博客 2万+

Redis-Lua脚本详解

Redis中执行Lua脚本 SCRIPT LOAD 和 EVALSHA指令 错误处理函数pcall()与call() Script Kill 的原理

哆啦A梦 4128

论文阅读笔记:Extended Vision Transformer (ExViT) for Land Use and Land Cover Classification

注意力机制驱动的深度模型最近取得了成功,如最具代表性的视觉转换器(ViT),吸引了一波高级研究来探索它们对更广泛领域的适应。然而,遥感(RS)领域中基于Transformer的方法更关注单模态数据,这可能会在充分利用不断增长的多模态地球观测数据时失去可扩展性。为此,我们提出了一种新的多模式深度学习框架,通过在最小修改的情况下扩展传统的ViT,针对土地利用和土地覆盖(LULC)分类任务。

嗑研狗的日常 945

半桥LLC谐振变换器及同步整流MATLAB仿真(二)

接上文,半桥LLC谐振变换器及同步整流MATLAB仿真

qq_55203246的博客 4331

redis释放锁-lua脚本

分布式锁 redis释放锁-lua脚本

高艳艳的博客! 587

RK3568 上C图像camera图像采集应用实例(二)

本文探索rk3568上实现C语言的 通过C v4l2 接口 采集图像 ,刷屏控制 drm的显示camera图像中 实现camera preview 预览 的实践和探索。

luoshanxuli2010的专栏 763

Redis系列:redis实现分布式锁

基于 Redis 实现一个通用的分布式锁组件。 整体模式 Jmeter发压到Nginx上,Nginx在负载到两台应用上,应用去redis上扣款,组成分布式环境。 注意在实验的时候,可以打包两个端口不同的jar包,也可以在idea上开启Allow parallel run达到实验目的。 SpringBoot jar启动报错:S

ljfirst的博客 3955

【OpenClaw从入门到精通】第73篇:30天OpenClaw实战挑战——从零搭建个人数字助理(Day15-21)万字超详细高阶实战版

经过前两周的基础部署与功能搭建,你已拥有可自动化干活的AI助理与数字员工团队,但距离“高阶精通”仍有差距。本文聚焦第三周(Day15-21)核心实战,围绕安全审计、语音能力接入、Token成本控制、Agent Loop优化、One-Liner指令五大核心模块,结合真实落地案例与踩坑经验,提供超详细实操指南。通过本文,你将掌握生产级安全加固方案、语音交互全流程配置、低成本高性价比使用策略、Agent自主闭环优化技巧,以及一句话搞定复杂任务的高效指令用法,同时完成中期复盘与最后九天冲刺规划

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 364

Vue3 - H5实现省市区三四级联动组件,选择地址自定义省市区三级联动插件,弹框式多级联动选择器区域选择,vue3实现省市区三级联动地址选择组件(支持接口数据懒加载,样式精美漂亮,附带详细示例源码)

vue3实现省市区三级联动地址选择组件(附address文件),vue3实现省市区三级联动, 实现省、市、县地区三级联动功能,vue3省市区选择器,VUE3 h5如何实现省市区街道的四级联动选择,vue实现省市区选择联动,vue3城市三级联动(自定义组件)_VUE三级联动,插件省市区联动,vue如何实现省市区选择器,vue3怎样实现省市区地址三级联动,vue四级联动,vue3级联选择器,vue3实现选择省市区镇(街道)四级级联选择,包含三级级联选择,省市区街道三级四级联动选择器,VUE3自定义多列选择器省市

🏆 前端领域优质创作者 3070

redis系列:基于redis的分布式锁

一、介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁。会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁。 本篇文章会将分布式锁的实现分为两部分,一个是单机环境,另一个是集群环境下的Redis锁实现。在介绍分布式锁的实现之前,先来了解下分布式锁的一些信息。 二、分布式锁 2.1 什么是分布式锁? 分布式锁是控制分布式系统或不同系统之间共同访问共享资源...

星辉Johnson的博客 334

HTML炫酷烟花④(完整代码)

HTML语言实现炫酷烟花的完整代码。

AIGC 9万+

Redis面试系列:Redis实现分布式锁

Redis实现分布式锁 前言 分布式锁的实现有三种方式 数据库乐观锁 基于Redis的分布式锁 基于Zookeeper的分布式锁 分布式锁满足的条件 为了确保分布式锁可用,我们至少要保证锁的实现同时满足以下几个条件 互斥性:在任意时刻只有一个客户端能持有锁 不会死锁:即使有一个客户端在持有锁的期间发生崩溃而没有主动解锁,也能保证后续其它客户端能加锁 容错性:只要大部分的Redis节点正常运行,客户端就可以加锁和解锁 解铃还须系铃人:加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解除 加锁

Viper的程序员修炼手册 2272

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

吃透Redis系列:分布式锁

欢迎关注微信公众号:互联网全栈架构在分布式应用系统中,如果需要控制共享资源的访问,就需要用到分布式锁。分布式锁是相对于单机锁而言的,在一个单体系统或者单个进程中,我们可以用synchroinzed这样的关键字对共享资源加锁,然而,系统一旦分布式部署,这样的手段就没有效果了。记得几年前有一次面试,一个工作五六年的年轻小伙,说他们的系统是集群部署的,可以横向扩展,根据业务要求,系统每天凌晨还会运行一个...

weixin_44742132的博客 1262

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Redis系列:使用Redis实现分布式锁及相关问题

分布式锁其实就是,控制分布式系统不同进程共同访问共享资源的一种锁的实现。如果不同的系统或同一个系统的不同主机之间共享了某个临界资源,往往需要互斥来防止彼此干扰,以保证一致性。 本篇内容包括:关于 Redis 与 分布式锁,Redis 分布式锁的问题及解决方式,Redis 中的 Lua 脚本 以及 Redis 中的 RedLock 算法!

栗筝i的博客 6359

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

NoSql之Redis系列四: Redis实现分布式锁

[OTC](NoSql之Redis系列四: Redis实现分布式锁) 前言 分布式锁的实现方式很多, 可以使用 数据库乐观锁, 可以适用 Zookeeper, 可以使用Redis, 本文总结一下Redis的分布式锁的常用方式. Redis分布式锁的特点 安全: 在任一时刻, 只有一个客户端持有锁, 同一把锁相互排斥. 保活1: 无死锁, 持有锁的客户端崩溃或者网络断开, 也可以获取新锁 保活2:...

wau_hua的博客 414

Redis系列教程(八):分布式锁的由来、及Redis分布式锁的实现详解

在很多场景中,我们为了保证数据的最终一致性,需要很多的技术方案来支持,比如分布式事务、分布式锁等。那具体什么是分布式锁,分布式锁应用在哪些业务场景、如何来实现分布式锁呢?今天来探讨分布式锁这个话题。 什么是分布式锁 要介绍分布式锁,首先要提到与分布式锁相对应的是线程锁、进程锁。 1.线程锁 主要用来给方法、代码块加锁。当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段。线程锁只在同一JVM中有效果,因为线程锁的实现在根本上是依靠线程之间共享内存实现的,比如Sy...

一个有情怀的程序猿博客 559

科普文:Redis系列之【Redis实践之分布式锁中的坑】

本文将给大家分析阐述,Redis分布式锁的12个坑,建议直接用redisson实现的分布式锁,可以避免踩坑,需要的朋友可以参考下。其实,在我们绝大多数分布式业务场景中,使用redis分布式锁就够了,真的别太较真。因为数据不一致问题,可以通过最终一致性方案解决。但如果系统不可用了,对用户来说是暴击一万点伤害。可以参考前面三篇文章,有条件的尽量选择Etcd实现的分布式锁,其次是ZK;一般Redisson的分布式锁能够满足我们大多数业务场景。 具体抉择仅供参考,一切从实际触发。

为无为,事无事,味无味。 1470

Redis深入解析系列:分布式锁详解

单机版实现 SET resource_name my_random_value NX PX 30000 失效时间保障锁最终会被释放,my_random_value 保证锁能被正确释放 释放锁操作用你lua脚本实现: if redis.call("get",KEYS[1]) == ARGV[1] then return redis.call("del",KEYS[1]) else r...

Link的博客 132

Redis系列(二):Redis的分布式锁解析及应用

在开发中,一个进程中多个线程需要竞争某一资源的时候,我们通常会用一把锁来保证只有一个线程获取到资源。如加上synchronize关键字或ReentrantLock锁等操作。但如果是多个进程相互竞争一个资源,如何保证资源只会被一个操作者持有呢?比如在微服务的架构下,多个应用服务要同时对同一条数据做修改,要确保数据的正确性,那就只能有一个应用修改成功。

鳄鱼儿 925
上一篇: 跋山涉水——深入 Redis 字典遍历
下一篇: NGINX功能详解
普通网友
博客等级 码龄8年 55粉丝 197原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值