乐观锁的使用场景

乐观锁是一种轻量级锁,在并发竞争不激烈的场景下,我们可以使用乐观锁来保证线程安全。

我们来看一个场景:定时job如何做并发控制,保证只有一台服务器执行?

这个场景其实很适合使用乐观锁,因为我们的跑job的服务器节点不会太多,可能就几台,几十台。

如何使用呢?我们可以参考一下CAS的实现。

首先每条job都会配置在数据库中,初始状态是N,如果有job开始跑了,会先把状态置为Y。

并发场景我们是这样考虑的,拿预期值和修改值去更新这条数据,sql是这样的:

 

 

 

 

 

 

 

update 
    job_table jt
set
    jt.status = 'Y',
    jt.update_date = sysdate
where
    jt.job_code = 'job_a_code' and
    jt.status = 'N'

 

这里做一下简单说明:

首先,我们有一个期望值N,也就是说,只有期望值是N,我才会去修改job的状态字段。

这个期望值,我们可以理解成CAS中的内存值。

然后呢?CAS还有一个修改值,也就是我们传过来的Y,我们把状态字段置为Y,告诉其他线程,这个job已经在跑了。

CAS还有一个原始值,也就是我们这里的入参N。注意这里的原始值和期望值的区别。

 

OK,完美,三个值都有了,

期望值N

修改值Y

原始值N

接下来就是使用CAS来进行并发控制了。

如果线程A和线程B同时过来了,都要修改job的状态字段,由于我们在应用层没有加锁,这两个线程同时到达了数据库,

如果我们采用oracle/mysql的默认隔离级别的话,那么因为是修改同一条数据,数据库会加锁,也就是说这2个请求会

排队,依次执行。假设线程B先执行了,然后线程A去执行的时候,发现期望值是Y,不符合预期,那么线程A就会认为有

其他线程修改了job字段的值,这时候线程A修改失败,直接返回了。

 

然后在应用层面,我们可以根据我们的update语句的返回值,来判断,如果修改成功了,那么update语句返回的值是1,

也就是修改了一条记录。这是我认为我成功的获得了job锁,接着开始执行job。否则,update语句返回的值是0,获取锁失败,直接退出job。

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值