你应该知道的乐观锁-高效控制线程安全的手段

本文介绍了在Seata分布式事务框架中遇到的并发问题,并探讨了悲观锁和乐观锁的使用。在面对低概率并发冲突时,文章推荐使用乐观锁,特别是在数据库中通过版本号实现,以及在代码中利用CAS自旋实现轻量级锁。同时,文章提到了锁的优化,包括超时机制和锁膨胀策略,以确保在保证线程安全的同时提高性能。
摘要由CSDN通过智能技术生成

1.背景

最近在修改Seata线程并发的一些问题,把其中一些经验总结给大家。先简单描述一下这个问题,在Seata这个分布式事务框架中有个全局事务的概念,在大多数情况下,全局事务的流程基本是顺序推进不会出现并发问题,但是当一些极端的情况下,会出现多线程访问导致我们全局事务处理不正确。 如下面代码所示: 在我们全局事务commit阶段,有一个如下代码:

  if (status == GlobalStatus.Begin) {
   
        globalSession.changeStatus(GlobalStatus.Committing);
    }

代码有些省略,就是先判断status状态是否Begin状态,然后改变状态为Committing。

在我们全局事务rollback阶段,有一个如下代码:

if (status == GlobalStatus.Begin) {
   
            globalSession.changeStatus(GlobalStatus.Rollbacking);
        }

同样的也省略了部分代码,这里先判断status状态是否为begin,然后改变为Rollbacking。这里再Seata的代码中并没有做一些线程同步的手段,如果这两个逻辑同时执行(一般情况下不会,但是极端情况下可能会出现),会让我们的结果出现不可预料的错误。而我们所要做的就是解决这种极端情况下来的并发出现的问题。

2.悲观锁

对于这种并发出现问题我相信大家第一时间想到的肯定是加锁,在Java中我们我们一般采用下面两个手段进行加锁:

Synchronized
ReentrantLock
我们可以利用Synchronized 或者 ReentrantLock进行加锁,可以将代码修改成下面的逻辑:

synchronized:

synchronized(globalSession){
   
            if (status == GlobalStatus.Begin) {
   
                globalSession.changeStatus(GlobalStatus.Rollbacking);
            }
        }

ReentrantLock进行加锁:

reentrantLock.lock();
 try {
   
    if  (status == GlobalStatus.Begin
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值