开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 19 天,点击查看活动详情”
前言
今天我们一起来研究在多线程基础下,可能会发生的一些业务问题,以及对应问题的解决方式。
实际案例
在进行一些业务中,我们常常会遇到有限制的购买和订阅。我们一般的解决方法就是通过判断数据库的内存是否足够,然后进行对应后续的操作。这在单线程下几乎是没有什么问题的,可是一旦涉及到多线程。尤其是在临界条件下,大量请求就会造成数据库的判断结果出错,比如说库存问题,当我们设置的条件为库存大于0时,在多线程的情况下往往会多卖出几件(大伙可以用jmter去进行测试),这是因为当数据库的库存还未1时,同时进入的几个线程多会拿到库存大于0的结果,从而导致超卖问题。那么接下来就要是用乐观锁的时候了。
什么是乐观锁
乐观锁就是为了应对多线程问题的(多线程问题的解法大概就是加锁,还有一种是悲观锁)。乐观锁认为这个线程问题哪里能那么容易发生呢?因此就不加锁(如Synchronized、Lock这些),只是在更新的时候采取判断有没有其他的线程进行数据的修改。像是这里的问题的话,就直接在判断的时候加个条件库存也大于0就好了。
boolean success = seckillVoucherService.update()
.setSql("stock = stock -1 ").eq("voucher_id", voucherId)
.gt("stock", 0).update();
但是一般的同届的需要加入一个版本号,在进行修改的时候将版本号也查出来,最后在修改的时候加入版本号作为条件。
乐观锁的优缺点
乐观锁因为不用整个加锁,所以性能比较好,但是也因为此所以乐观锁的成功率相较于悲观锁也比较低。