WCS程序开发时,添加乐观锁的思考

背景:出库时,采用定时任务检查每个出库口的状态,出库口可用则选择一个该出库口的任务执行。

当切换出入库模式时,先判断是否有正在执行中的任务,没有执行中的任务时,才可以切换为入库模式。

‍♂️抽象一下:

线程一 线程二
1.检查出库口状态 a.判断执行中的任务数量
2.执行任务 b.关闭出库口

两个线程分别在两个事务中执行,也属于两个不同线程。如果不加锁,难免会出现一些问题:

1.此时执行中的任务数量为0 ,执行过程如果是 a 1 2 b 或者 1 a 2 b ,只要满足b在1之后 a在2之前,就会出现冲突。最终的结果就是任务执行了,出库口被关闭了。

最简单的是添加悲观锁,同时只有一个线程被执行。

如果采用乐观锁的方式怎么解决呢?

分析:导致冲突的根本原因是对于 多个任务和一个出库口资源的竞争。站在线程一的角度,检查出库状态没有问题,在检查完成后一直到事务被提交,如果其他线程更改了出库口的状态,必然会出问题。站在线程二的角度,同理,在判断完任务数量之后,如果在事务提交之前,有其他改变了执行中的任务数量,也会出现问题。

乐观锁是在所竞争的资源上加锁。

如果给多个未执行的任务加锁,那么两个线程在执行完后,需要更新一下所有的任务。由于线程一最后本身就是更新了任务状态,所以只需要在线程二执行完成后,空更新一下所有的任务状态,看是否发生冲突。

如果给出库口加锁,同理也是只需要在线程一最后添加一个空更新出库口的操作,检查是否发生冲突。

再次判断如果按照a 1 2 b或者a 1 b 2 或者 1 a 2 b 或者 1 a b 2的方式执行时候发生线程冲突。

给出库口加锁

如果给出库口加锁,两个线程的操作变成下面的样子

线程一 线程二
1.检查出库口状态 a.判断执行中的任务数量
2.执行任务 b.关闭出库口
3.空更新出库口

我们站台线程一角度分析,在执行完3之后,如果有冲突,直接回滚事务,所以说如果线程一能成功执行,那么就不会发生任务执行了,出库口状态异常的情况。

给所有任务加锁

如果给所有任务加锁,两个线程的操作变成下面的样子

线程一 线程二
1.检查出库口状态 a.判断执行中的任务数量
2.执行任务 b.关闭出库口
c.空更新所有的任务

同理,我们站在线程二分析会方便一点,如果线程二顺利执行,就不可能存在出库口被关闭,仍然存在任务数量不为0的情况。

考虑两种方式,肯定是选择出库口作为锁更合理。

你可能感兴趣的:(多线程,乐观锁)