收藏夹吃灰系列(十):一篇文教你如何快速实现乐观锁机制及适用场景 | 超级详

代码 代码 1289 人阅读 | 0 人回复

<
大家好,我是bug菌~~
       Hi ,小同伴们,我们又见面啦!先给大家说声歉仄,距离上一篇发文已经时隔快两个月了,至于为什么不实时更文了呢?有小同伴可能就会猜,要么是太忙要么就是转移到其他的博客上了...都不是啦,主要是自己的工作出了一点问题,导致我搁置了更文这件事,至于问题详细具体,此处就未便透露啦。好啦,话不多说,咱们就开始今天的活儿吧。
收藏夹吃灰系列(十):一篇文教你如何快速实现乐观锁机制及适用场景 | 超级详 205416vbn67uuodutddmyq.jpg

         今天,我主要是想简朴介绍一下乐观锁的实现及在什么场景下该使用乐观锁。 
那么,今天的第一个问题,什么是乐观锁呢?
  一、概念:

          乐观锁是相对悲观锁而言的,乐观锁假设数据一般情况不会造成辩论,所以在数据进行提交更新的时候,才会正式对数据的辩论与否进行检测,如果辩论,则返回给用户异常信息,让用户决定如何去做。
  乐观锁适用于读多写少的场景,这样可以提高程序的吞吐量。
          在Java中java.util.concurrent.atomic包下面的原子变量类{AtomicInteger}就是使用了乐观锁的一种实现方式CAS(Compare and Swap 比较并交换)实现的。
比如:看下边这张图,辅助你明白。
收藏夹吃灰系列(十):一篇文教你如何快速实现乐观锁机制及适用场景 | 超级详 205417j2g1ldygci1zy1el.png

          乐观锁采取了更加宽松的加锁机制。也是为了避免数据库幻读、业务处理时间过长等原因引起数据处理错误的一种机制,但乐观锁不会刻意使用数据库本身的锁机制,而是依据数据本身来保证数据的正确性。
收藏夹吃灰系列(十):一篇文教你如何快速实现乐观锁机制及适用场景 | 超级详 205417tyukf1nkh34k050f.jpg

 二、实现方式 

1、版本号机制

           一般是在数据表中加上一个版本号version字段,表示数据被修改的次数,一旦版本号和数据的版本号一致就可以执行修改操作并对版本号执行 +1 操作,否则就执行失败。因为每次操作的版本号都会随之增加,所以不会出现 ABA 问题。
  乐观锁实现过程:
  取出记载时:获取当前version
  更新时:带上这个version
  执行更新时:set version = newVersion where version = oldVersion
  如果version不相等,更新失败;
 如下具体介绍使用如何使用mybatis-plus 实现乐观锁
1、数据库表加字段:int version

收藏夹吃灰系列(十):一篇文教你如何快速实现乐观锁机制及适用场景 | 超级详 205417apuhhtfpuyrphr41.jpg

 2、实体该字段加@Version 注解
收藏夹吃灰系列(十):一篇文教你如何快速实现乐观锁机制及适用场景 | 超级详 205417xlm7ee73e7plylkp.jpg

  3、注册乐观锁插件
  1. /**
  2. * MybatisPlusConfig配置
  3. *
  4. * @Author luoYong
  5. * @Date 2021-08-10 21:41
  6. */
  7. @Configuration
  8. @MapperScan("com.system.xiaoma.dao")
  9. public class MybatisPlusConfig {
  10.    /**
  11.     * 注册乐观锁插件
  12.     */
  13.    @Bean
  14.    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
  15.       return new OptimisticLockerInterceptor();
  16.    }
  17. }
复制代码
4、test-case测试
收藏夹吃灰系列(十):一篇文教你如何快速实现乐观锁机制及适用场景 | 超级详 205418r7k2uf7l4qyp2c54.jpg

 用户数据更新成功,version也+1
收藏夹吃灰系列(十):一篇文教你如何快速实现乐观锁机制及适用场景 | 超级详 205418jk4rqkkrjq7q4h4k.jpg

 以上就是通过mybatis-plus 组件实现乐观锁机制;
收藏夹吃灰系列(十):一篇文教你如何快速实现乐观锁机制及适用场景 | 超级详 205418w8qw0wi8b8tituzo.jpg

2、CAS算法
  即compare and swap(比较和互换),是一种有名的无锁算法。无锁编程,即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被阻塞的情况下实现变量的同步,所以也叫非阻塞同步。CAS算法涉及到3个操作数。
  1、需要读写的内存值V
  2、进行比较的值A
  3、拟写入的新值B
  当且仅当V的值等于A时,CAS通过原子方式用新值B来更新V的值,否则不会执行任何操作(比较和替换是一个原子操作)。一般情况下是一个自旋操作,即不断的重试。
  
收藏夹吃灰系列(十):一篇文教你如何快速实现乐观锁机制及适用场景 | 超级详 205418mdfn2grszhzr2q32.png

          
          但是这样的CAS机制会带来一个比较常见的问题。那就是ABA问题。
  举个例子,你看到桌子上有100块钱,然后你去干其他事了,回来之后看到桌子上依然是100块钱,你就认为这100块没人动过,其实在你走的那段时间,别人已经拿走了100块,后来又还回来了。这就是ABA问题。
收藏夹吃灰系列(十):一篇文教你如何快速实现乐观锁机制及适用场景 | 超级详 205418obtbcucmmumtu6u7.jpg

 三、如何选择

在乐观锁与悲观锁的选择上面,主要看下两者的区别以及适用场景就可以了。

  • 响应效率:如果需要非常高的响应速度,发起采取乐观锁方案,成功就执行,不成功就失败,不需要等待其他并发去释放锁。乐观锁并未真正加锁,效率高。一旦锁的粒度掌握欠好,更新失败的概率就会比较高,容易发生业务失败。
  • 辩论频率:如果辩论频率非常高,发起采取悲观锁,保证成功率。辩论频率大,选择乐观锁会需要多次重试才气成功,代价比较大。
  • 重试代价:如果重试代价大,发起采取悲观锁。悲观锁依赖数据库锁,效率低。更新失败的概率比较低。
  • 乐观锁如果有人在你之前更新了,你的更新应当是被拒绝的,可以让用户从新操作。悲观锁则会等待前一个更新完成。这也是区别。
随着互联网三高架构(高并发、高性能、高可用)的提出,悲观锁已经越来越少的被应用到生产环境中了,尤其是并发量比较大的业务场景。
收藏夹吃灰系列(十):一篇文教你如何快速实现乐观锁机制及适用场景 | 超级详 205419z4h4lm73v4dqxued.png


 往期热文推荐:



 OK,今天的文章先写到这。如果问题还请批评指正。
收藏夹吃灰系列(十):一篇文教你如何快速实现乐观锁机制及适用场景 | 超级详 205419tqzp8q8xz787xaxd.gif

  ❤如果文章对您有所资助,就请在文章末尾的左下角把大拇指点亮吧!(#^.^#);
  ❤如果喜欢bug菌分享的文章,就请给bug菌点个关注吧!(๑′ᴗ‵๑)づ╭❤~;
  ❤对文章有任何问题欢迎小同伴们下方留言大概入群探讨【群号:708072830】;
  ❤鉴于个人经验有限,所有观点及技术研点,如有异议,请直接复兴参与讨论(请勿发表攻击言论,谢谢);
  ❤版权声明:本文为博主原创文章,转载请附上原文出处链接和本文声明,版权所有,盗版必究!(*^▽^*).

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
1、本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,按照目前互联网开放的原则,我们将在不通知作者的情况下,转载文章;如果原文明确注明“禁止转载”,我们一定不会转载。如果我们转载的文章不符合作者的版权声明或者作者不想让我们转载您的文章的话,请您发送邮箱:Cdnjson@163.com提供相关证明,我们将积极配合您!
2、本网站转载文章仅为传播更多信息之目的,凡在本网站出现的信息,均仅供参考。本网站将尽力确保所提供信息的准确性及可靠性,但不保证信息的正确性和完整性,且不对因信息的不正确或遗漏导致的任何损失或损害承担责任。
3、任何透过本网站网页而链接及得到的资讯、产品及服务,本网站概不负责,亦不负任何法律责任。
4、本网站所刊发、转载的文章,其版权均归原作者所有,如其他媒体、网站或个人从本网下载使用,请在转载有关文章时务必尊重该文章的著作权,保留本网注明的“稿件来源”,并自负版权等法律责任。
回复 关闭延时

使用道具 举报

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

本版积分规则