20240227

乐观锁和悲观锁

悲观锁:认为线程安全问题一定会发生,因此在操作数据之前先获取锁,确保线程串行执行,例如Synchronized、Lock都属于悲观锁。

乐观锁:认为线程安全问题不一定会发生,因此不加锁,只是在更新数据时去判断有没有其它线程对数据做了修改,若未修改则认为是安全的,自己才更新数据;若已经被其它线程修改说明发生了安全问题,此时可以重试或异常。

乐观锁实现的两种方式:

版本号法:

以黑马点评为例的原理图如下

在每一次进行修改操作时,需判断数据是否被修改过,这里对数据库字段增加了版本号,对数据进行一次修改操作,则版本号加1,上图中线程1修改后版本号变为2,每次在修改操作判断时,查询条件使用的版本号为上一次查询数据的版本号。

CSA法:

以黑马点评为例的原理图如下

该方法在修改前直接根据所需查询的数据是否相较于上一次查询到的值发生变化,从而判断是否有其他线程修改过数据,上图中线程1、2在进行修改操作前判断时查询条件为:所需修改的字段=该线程上一次查询到该字段数据的数值。

CAS方法存在一定弊端,虽然能解决超卖问题,但会导致失败率大大增加,例如线程a查询到的stock值为10,完成查询后,中间有5个线程紧接着进行查询,这5个线程查完后,线程a进行修改,此时由于stock为10,与初次查询的是一样的,因此执行修改操作,stock减1变为9,此时后面5个线程进行修改操作判断时,查询条件中的stock仍为10,而数据库中stock的值为9,因此此时认为别的线程对该值进行了修改,故这些线程的修改操作会失败。

此时的优化方法:stock条件设置为stock > 0,表示每一次判断是否大于0,满足时再修改。

全部评论

相关推荐

1 5 评论
分享
牛客网
牛客企业服务