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

Posted bug菌√

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了收藏夹吃灰系列:一篇文教你如何快速实现乐观锁机制及适用场景 | 超级详细,建议收藏!相关的知识,希望对你有一定的参考价值。

大家好,我是bug菌~~

       Hi ,小伙伴们,我们又见面啦!先给大家说声抱歉,距离上一篇发文已经时隔快两个月了,至于为什么不及时更文了呢?有小伙伴可能就会猜,要么是太忙要么就是转移到其他的博客上了...都不是啦,主要是自己的工作出了一点问题,导致我搁置了更文这件事,至于问题详细具体,此处就不便透露啦。好啦,话不多说,咱们就开始今天的活儿吧。

         今天,我主要是想简单介绍一下乐观锁的实现及在什么场景下该使用乐观锁。 

那么,今天的第一个问题,什么是乐观锁呢?

一、概念:

        乐观锁是相对悲观锁而言的,乐观锁假设数据一般情况不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果冲突,则返回给用户异常信息,让用户决定如何去做。

乐观锁适用于读多写少的场景,这样可以提高程序的吞吐量。

        在Java中java.util.concurrent.atomic包下面的原子变量类{AtomicInteger}就是使用了乐观锁的一种实现方式CAS(Compare and Swap 比较并交换)实现的。

比如:看下边这张图,辅助你理解。

        乐观锁采取了更加宽松的加锁机制。也是为了避免数据库幻读、业务处理时间过长等原因引起数据处理错误的一种机制,但乐观锁不会刻意使用数据库本身的锁机制,而是依据数据本身来保证数据的正确性。

 二、实现方式 

1、版本号机制

         一般是在数据表中加上一个版本号version字段,表示数据被修改的次数,一旦版本号和数据的版本号一致就可以执行修改操作并对版本号执行 +1 操作,否则就执行失败。因为每次操作的版本号都会随之增加,所以不会出现 ABA 问题。

乐观锁实现过程:

取出记录时:获取当前version

更新时:带上这个version

执行更新时:set version = newVersion where version = oldVersion

如果version不相等,更新失败;

 如下具体介绍使用如何使用mybatis-plus 实现乐观锁

1、数据库表加字段:int version

 2、实体该字段加@Version 注解

  3、注册乐观锁插件

/**
 * MybatisPlusConfig配置
 *
 * @Author luoYong
 * @Date 2021-08-10 21:41
 */
@Configuration
@MapperScan("com.system.xiaoma.dao")
public class MybatisPlusConfig {

   /**
    * 注册乐观锁插件
    */
   @Bean
   public OptimisticLockerInterceptor optimisticLockerInterceptor() {
      return new OptimisticLockerInterceptor();
   }
}

4、test-case测试

 用户数据更新成功,version也+1

 以上就是通过mybatis-plus 组件实现乐观锁机制;

2、CAS算法

即compare and swap(比较和互换),是一种有名的无锁算法。无锁编程,即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被阻塞的情况下实现变量的同步,所以也叫非阻塞同步。CAS算法涉及到3个操作数。

1、需要读写的内存值V

2、进行比较的值A

3、拟写入的新值B

当且仅当V的值等于A时,CAS通过原子方式用新值B来更新V的值,否则不会执行任何操作(比较和替换是一个原子操作)。一般情况下是一个自旋操作,即不断的重试。

        

        但是这样的CAS机制会带来一个比较常见的问题。那就是ABA问题。

举个例子,你看到桌子上有100块钱,然后你去干其他事了,回来之后看到桌子上依然是100块钱,你就认为这100块没人动过,其实在你走的那段时间,别人已经拿走了100块,后来又还回来了。这就是ABA问题。

 三、如何选择

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

  1. 响应效率:如果需要非常高的响应速度,建议采用乐观锁方案,成功就执行,不成功就失败,不需要等待其他并发去释放锁。乐观锁并未真正加锁,效率高。一旦锁的粒度掌握不好,更新失败的概率就会比较高,容易发生业务失败。
  2. 冲突频率:如果冲突频率非常高,建议采用悲观锁,保证成功率。冲突频率大,选择乐观锁会需要多次重试才能成功,代价比较大。
  3. 重试代价:如果重试代价大,建议采用悲观锁。悲观锁依赖数据库锁,效率低。更新失败的概率比较低。
  4. 乐观锁如果有人在你之前更新了,你的更新应当是被拒绝的,可以让用户从新操作。悲观锁则会等待前一个更新完成。这也是区别。

随着互联网三高架构(高并发、高性能、高可用)的提出,悲观锁已经越来越少的被应用到生产环境中了,尤其是并发量比较大的业务场景。


 往期热文推荐:


 OK,今天的文章先写到这。如果问题还请批评指正。

❤如果文章对您有所帮助,就请在文章末尾的左下角把大拇指点亮吧!(#^.^#);

❤如果喜欢bug菌分享的文章,就请给bug菌点个关注吧!(๑′ᴗ‵๑)づ╭❤~;

❤对文章有任何问题欢迎小伙伴们下方留言或者入群探讨【群号:708072830】;

❤鉴于个人经验有限,所有观点及技术研点,如有异议,请直接回复参与讨论(请勿发表攻击言论,谢谢);

❤版权声明:本文为博主原创文章,转载请附上原文出处链接和本文声明,版权所有,盗版必究!(*^▽^*).

以上是关于收藏夹吃灰系列:一篇文教你如何快速实现乐观锁机制及适用场景 | 超级详细,建议收藏!的主要内容,如果未能解决你的问题,请参考以下文章

Python万字博文教你玩透Beautiful Soup库,不信你学不会❤️建议收藏系列❤️

万字博文教你python爬虫必备XPath库,看完还不会我把我女朋友都给你❤️建议收藏系列❤️

❤️万字博文教你python爬虫必备XPath库,看完还不会我把我女朋友都给你❤️建议收藏系列

❤️万字博文教你python爬虫必备XPath库,看完还不会我把我女朋友都给你❤️建议收藏系列

万字博文教你python爬虫必备Beautiful Soup库,看完还不会我把我女朋友都给你❤️建议收藏系列❤️

乐观锁悲观锁,这一篇就够了!