小白科普:悲观锁和乐观锁

SpringMVC并发请求线程安全问题案例分析 背景:一个人的成长在于你经历了多少,正如古语有云“读万卷书,不如行万里路。”做技术尤其如此,要想快速成长,必须先多写代码,多思考,多总结,当然还可以通过帮助别人解决问题来验证或者激励自己的成长。今天这篇文章主要是基于一个朋友在实际开发中出现的一个并发案例,在帮助其解决的过程中,发现自己也有很多的知识误区,遂写此篇以作记录,同时也分享给大家。 一,案例描述 ①,业务需求 用户通过系统生成邀请二 阅读详情

旺财和小强生活在一个网上商城的系统中, 是一对儿线程好基友。 

星期一刚上班,旺财接到领导电话说,要把一个商品的库存减少20, 旺财不敢怠慢,赶快把库存取出来一看,哦,现在有1000个。

与此同时,小强也接到电话说要把同一商品的库存减少30, 他一看,哦,现在有1000个。

旺财计算出最新的库存值980, 保存!

小强也计算出最新的库存值970, 保存 !  

旺财的数据被小强覆盖了!

领导一看,本来卖出了50个商品,现在库存只扣了30个,这样持续下去就天下大乱了。 

旺财和小强, 各打二十大板, 长长记性!

小强说:“哥,要不我们还是想个办法吧,再这样下去要被打死的。”

旺财悲催地说: “这样, 以后我们每次访问库存之前,都要先加锁,加了锁,就禁止别人再进入访问,只能等待持有锁的人来释放。”

星期二, 领导让旺财再次把库存减少20 , 旺财这次万分小心,先把库存给锁住,然后慢慢修改。 

小强也接到了把库存减少的指令, 但是旺财哥已经把库存锁住了, 不能操作,小强只好去阻塞车间喝茶聊天,然后到就绪车间等待调度运行。 

好不容易等到可以再次执行了,小强一看,这库存怎么还锁着呢!? 只好再次去阻塞车间喝茶。 

领导一看, 小强你怎么回事, 老是喝茶聊天? !  还干不干活了?

小强争辩说旺财哥一直锁着库存,我没法操作。

领导不管这些, 把小强和旺财又打了二十大板。 

(备注: 这种加锁的方式就是悲观锁了,悲观锁正如其名,每次取读写数据时候总认为数据会被别人修改,所以将数据加锁,置于锁定状态, 不让别人再访问。缺点是如果持有锁的时间太长,其他用户需要等待很长时间。)

旺财说: “兄弟,这一次哥对不住你啊,处理得慢了一些, 不过哥刚才挨打的时候想了一个好办法:乐观锁。”

小强说:“拉倒吧你,屁股都快被打烂了还乐观?”

“你听我说嘛, 我们在那个库存字段的旁边,再加上一个版本(version)的字段, 例如刚开始的时候(库存= 1000, 版本=1), 每次你去读的时候不仅要读出库存,还要读出版本号, 等到你修改了库存,往回写的时候一定要检查一下版本号,看看和你读的时候是否一样。”

“如果不一样呢?”  小强问

“那就放弃这次写的操作,重新读取库存和版本号, 重新来过。”

“如果一样呢? ”

“那就放心大胆地把新的库存值写回去。把版本号也加1”

“我似乎有点明白了,我们试试,不过你要想好,我可不想再挨板子了。”

星期三, 旺财奉命把库存减去30, 他先读到了(库存= 1000, 版本=1);  小强也要改库存了,他要把库存减去50, 于是他也读到了(库存= 1000, 版本=1)。 

旺财计算出新的库存值970 ,写回成功,现在版本变成了(库存= 970, 版本=2)。 

小强也计算出新库存950 , 也准备写回,他战战兢兢地去看最新的版本号, 已经变成版本2了, 按照之前的约定,只好重新读取了。

小强再次读取(库存= 970, 版本=2) , 计算出最新缓存值920(970减去50), 再次试图更新,没想到又被别人抢了先,现在版本号已经变成3了 ,最新的数据是(库存= 900, 版本= 3)。

唉, 只好重新来过, 计算出最新缓存值850(900减去50),第三次终于更新成功了, 最新的库存是 (库存=850, 版本= 4)

领导看到旺财和小强忙得热火朝天,一刻不停,并且库存值也没有乱掉, 满意地点了点头:好同志啊。

(备注: 这种方式就是所谓的乐观锁了,旺财和小强这次乐观了一点,觉得一般情况下不会有太多人修改库存,所以没有加锁,放心地去操作,只有在最后更新的时候才去看是否冲突。 这种方式适合于冲突不多的场景,如果冲突很多,数据争用激烈,会导致不断地尝试,反而降低了性能。)

你看到的只是冰山一角, 更多精彩文章,请移步《2016文章精华》或者《2017上半年文章精华》


640?

优秀人才不缺工作机会,只缺适合自己的好机会。但是他们往往没有精力从海量机会中找到最适合的那个。

100offer 会对平台上的人才和企业进行严格筛选,让「最好的人才」和「最好的公司」相遇。

扫描下方二维码,注册 100offer,谈谈你对下一份工作的期待。一周内,收到 5-10 个满足你要求的好机会!

0?wx_fmt=jpeg

AXI Timer IP核使用说明 AXI Timer是提供定时技术功能的集成IP核,具有时间生成、事件捕获、产生PWM波以及产生中断的功能,下面具体讲述Timer IP核的使用说明。 阅读详情

相关推荐

Uni-App推送踩坑实录:从云函数URL化到后台推送失效,我都经历了什么

本文详细记录了Uni-App开发者在接入uni-push 2.0时遇到的推送失效问题,从云函数URL化到后台推送失效的完整排查过程。通过系统化分析和与官方沟通,最终找到解决方案,并分享了预防措施与最佳实践,帮助开发者避免类似问题。

weixin_42552716的博客 487

Java 悲观锁 乐观锁

悲观锁:悲观锁在操作数据时比较悲观,认为别人会同时修改数据。因此操作数据时直接把数据锁住,直到操作完成后才会释放锁;上锁期间其他人不能修改数据。乐观锁:乐观锁在操作数据时非常乐观,认为别人不会同时修改数据。因此乐观锁不会上锁,只是在执行更新的时候判断一下在此期间别人是否修改了数据:如果别人修改了数据则放弃操作,否则执行操作。

qq_57570052的博客 1904

基于STM32的HC-SR04超声波模块测距(新手级)

本人是嵌入式新手,学习了STM32的部分内容,最近想找些项目做,然后顺便学习了一下HC-SR04超声波模块,学习过程中也参考了一些大佬的文章。本文记录了自己的学习方法和学习过程,同时也希望能和各位大佬交流讨论。

weixin_63758495的博客 2206

Java知识学习04(乐观锁和悲观锁)

乐观锁 悲观锁

ldy007714的博客 1065

通达信烽火起爆指标公式

STICKLINE(IF(起爆666,-120,0),+33,0,3.4,0),COLOR007777;STICKLINE(IF(起爆666,-120,0),+33,0,1.8,0),COLOR009999;STICKLINE(IF(起爆666,-120,0),+33,0,1.2,0),COLOR00BBBB;STICKLINE(IF(起爆666,-120,0),+33,0,0.6,0),COLOR00DDDD;STICKLINE(起爆666,0,100,9999,0)*起爆,COLOR000000;

zhibiaogong的博客 3901

安卓设备通过USB串口与STM32单片机通讯之一

这里写自定义目录标题欢迎使用Markdown编辑器`在这里插入代码片`新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 欢迎使用Markdown编辑器在这里插入代码片 你好下Markdown的基本语法知识。 新的改变 我们对

JGB联合商务组的博客 7246

Java多线程锁技术漫谈:乐观锁VS悲观锁

在多线程编程中,锁技术是常用的保证数据安全的方式。常见的锁技术包括乐观锁和悲观锁。本文将通过实例介绍乐观锁与悲观锁的实现方法,以及它们的优缺点,帮助开发者更好地了解和运用Java多线程的锁技术,提高并发性能和数据安全性。

洛阳泰山的博客 2490

Unity插件-Mirror使用方法(一)Mirror介绍

Unity Mirror 是一个专为 Unity 引擎设计的开源、社区驱动的网络库,主要用于简化多人联机游戏的开发。它最初是为了替代 Unity 原生的 UNet 系统(已被官方弃用)而创建的,因其轻量、灵活和高效的特点,成为 Unity 开发者构建多人游戏的热门选择。

qq_44501691的博客 4101

java的悲观锁和乐观锁

AtomicInteger,他的底层是Unsafe,他保证修改变量的时候是一个原子操作,我们现在想修改Account中的共享变量,修改之前我们要知道修改的成员变量的偏移位置,我们通过Unsafe对象里面一个方法,参数是修改的类型,变量名。线程只有占有了锁,才能去操作共享变量,每次只有一个线程占锁成功,获取锁失败的线程,都得停下来等待。无需加锁,每次只有一个线程能成功修改共享变量,其它失败的线程不需要停止,不断重试直至成功。锁时,如果锁已被占用,都会做几次重试操作,减少阻塞的机会。支持,且线程数不应超过。

weixin_43162044的博客 2206

【WRF-Chem 工具】CAMStoWRF详解:CAMS数据下载及处理

【WRF-Chem 工具】CAMStoWRF详解:CAMS数据下载及处理

WW、forever的博客 197

第 1 章 Prometheus 监控 | Prometheus 入门

了解 Prometheus 监控系统,学会安装及了解页面功能。

甘蓝的专栏 486

面试必备之乐观锁与悲观锁

悲观锁总是假设最坏的情况,认为共享资源每次被访问的时候就会出现问题(比如共享数据被修改),所以每次在获取资源操作的时候都会上锁,这样其他线程想拿到这个资源就会阻塞直到锁被上一个持有者释放。也就是说,共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程。像 Java 中和等独占锁就是悲观锁思想的实现。悲观锁通常多用于写多比较多的情况下(多写场景),避免频繁失败和重试影响性能。

JavaGuide 30万+

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

悲观锁和乐观锁

旺财和小强生活在一个网上商城的系统中, 是一对儿线程好基友。  星期一刚上班,旺财接到领导电话说,要把一个商品的库存减少20, 旺财不敢怠慢,赶快把库存取出来一看,哦,现在有1000个。 与此同时,小强也接到电话说要把同一商品的库存减少30, 他一看,哦,现在有1000个, 旺财计算出最新的库存值980, 保存!

zl 1155

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

悲观锁和乐观锁详解

公众号里有篇文章讲悲观锁和乐观锁小白科普:悲观锁和乐观锁,非常通俗易懂,在这里总结下自己的理解。 悲观锁:每次读写的时候讲数据加锁,不让别人访问,直到自己用完后释放。     缺点:是如果持有锁的时间太长,其他用户需要等待很长时间。 乐观锁:加一个版本(version)字段,每次讲版本读出,修改数据的时候对比下版本号是否一样。如果不一样放弃这次操作,重新读取再操作。     缺点:这...

weixin_34111819的博客 90

科普文:深入理解并发下的CAS机制

今天花了点时间了解了一下JDK1.8中的实现,发现它实现的主要思想就是依赖于CAS机制。CAS机制是并发中比较重要的一个概念,所以今天这篇博客就来详细介绍一下CAS机制以及Java中对CAS的适用。CAS全称需要修改的数据的内存地址(V);对这个数据的旧预期值(A);需要将它修改为的值(B);修改前记录数据的内存地址V;读取数据的当前的值,记录为A;修改数据的值变为B;查看地址V下的值是否仍然为A,若为A,则用B替换它;

为无为,事无事,味无味。 984

StampedLock源码分析

文章目录前言乐观锁 or 悲观锁源码分析构造函数读锁相关API乐观读锁的实现读锁的获取读锁的释放写锁相关API写锁的获取写锁的释放其他API读锁转写锁写锁转读锁转乐观锁ReadLockView和WriteLockView注意事项参考资料 前言 之前已经说过了ReentrantLock ReentrantReadWriteLock,可以参考之前的博客。在ReentrantReadWriteLock源...

xindoo 1612

JAVA小强从小就喜欢生命科学,小强

小白科普:悲观锁和乐观锁2021-03-11 22:30:17旺财和小强生活在一个网上商城的系统中, 是一对儿线程好基友。星期一刚上班,旺财接到领导电话说,要把一个商品的库存减少20, 旺财不敢怠慢,赶快把库存取出来一看,哦,现在有1000个。与此同时,小强也接到电话说要把同一商品的库存减少30, 他一看,哦,现在有1000个。旺财计算出最新的库存读书笔记-小强升职记2021-02-18 22:3...

weixin_42638178的博客 577

科普文:Java面试一问一答系列之九

锁是多线程编程中的同步机制,用于控制多个线程对共享资源的访问。锁可以防止多个线程同时访问临界区,从而保证数据的一致性和正确性。ReentrantLock: 是一个可重入的锁,支持公平和非公平两种模式。它提供了更丰富的功能,如条件变量、可中断的锁获取以及超时获取等。synchronized: 是Java中的内置锁,用于实现基本的同步。每个对象都有一个内置的监视器锁,可以通过synchronized关键字来获取和释放锁。死锁是指多个线程相互等待彼此持有的资源而无法继续执行的情况。

为无为,事无事,味无味。 1147

mysql锁详细解析

课程内容 1.mysql锁基础 2乐观锁于悲观锁的解释 3.死锁的产生和处理 4.间隙锁于行锁升级为表锁 1.0所谓表级锁,它直接锁住的是一个表,开销小,加锁快,不会出现死锁的情况,锁定粒度大,发生锁 冲突的概率更高,并发度最低 2.0所谓行级锁,它直接锁住的是一条记录,开销大,加锁慢,发生锁冲突的概率较低,并发度很高。 所谓页级锁,它是锁住的一个页面,在 InnoDB 中一个页面为16KB,它的开销介于表级锁和行级锁中 间,也可能会出现死锁,锁定粒度也介于表级锁和行级 锁中间,并发度也介于表级锁和行级

xiaonanhaijing的博客 204

CAS原理分析及ABA问题详解

这里写目录标题compare and swap, CAS概述应用ABA问题实现CAS的缺点转载wait-free lock-free本博客是博主个人学习时的一些记录,不保证是为原创,如有侵权请与我联系。 compare and swap, CAS 比较并交换(compare and swap, CAS),是原子操作的一种,可用于在多线程编程中实现不被打断的数据交换操作,从而避免多线程同时改写某一数据时由于执行顺序不确定性以及中断的不可预知性产生的数据不一致问题。 该操作通过将内存中的值与指定数据进行比较,当

weixin_42952928的博客 727

科普文:软件架构设计之【Resutful Api设计梳理-下】

继续总结下接口设计需要注意的点。尽量每种都给出具体的场景、案例等,希望大家能有所收获。1、接口幂等 2、读写分离 3、数据缓存 9、接口安全 7、设计模式 4、接口分页 5、接口加锁 6、事务管理

为无为,事无事,味无味。 1277

科普文:微服务之微服务改造【接口幂等性】设计

什么是接口幂等性?同一个接口,多次发出同一个请求,必须保证操作只执行一次。调用接口发生异常并且重复尝试时,总是会造成系统所无法承受的损失,所以必须阻止这种现象的发生。微服务框架下,微服务接口需要保证:接口幂等性。科普文:万字细说微服务及其框架Netflix,Spring Cloud,Spring Cloud Alibaba梳理-优快云博客当出现消费者对某条消息重复消费的情况时,重复消费的结果与消费一次的结果是相同的,并且多次消费并未对业务系统产生任何负面影响,那么这个消费者的处理过程就是幂等的。

为无为,事无事,味无味。 1028

科普文:JUC系列之Java 中15种锁简介

lock()方法利用的CAS,当第一个线程A获取锁的时候,能够成功获取到,不会进入while循环,如果此时线程A没有释放锁,另一个线程B又来获取锁,此时由于不满足CAS,所以就会进入while循环,不断判断是否满足CAS,直到A线程调用unlock方法释放了该锁。代码也比较简单,使用原子引用来存放线程,同一线程两次调用lock()方法,如果不执行unlock()释放锁的话,第二次调用自旋的时候就会产生死锁,这个锁就不是可重入的,而实际上同一个线程不必每次都去释放锁再来获取锁,这样的调度切换是很耗资源的。

为无为,事无事,味无味。 1432
上一篇: 从兄弟到父子:动态代理在民间是怎么玩的?
下一篇: 爱炫耀的数据库老头儿
码农翻身
码农翻身 《码农翻身》作者 《码农翻身》作者
博客等级 码龄8年 3万+粉丝 1084原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值