乐观锁 悲观锁 概念

乐观锁:乐观锁在操作数据时非常乐观,认为别人不会同时修改数据。

因此乐观锁不会上锁,只是在执行更新的时候判断一下在此期间别人是否修改了数据:

如果别人修改了数据则放弃操作,否则执行操作。

悲观锁:悲观锁在操作数据时比较悲观,认为别人会同时修改数据。

因此操作数据时直接把数据锁住,直到操作完成后才会释放锁;上锁期间其他人不能修改数据。

乐观锁 悲观锁 实现方式

悲观锁的实现方式是加锁,加锁既可以是对代码块加锁(如Java的synchronized关键字),也可以是对数据加锁(如MySQL中的排它锁)。

在mysql中的innoDB引擎下:

要使用悲观锁,我们必须关闭mysql数据库中自动提交的属性,命令set autocommit=0;即可关闭,因为MySQL默认使用autocommit模式,也就是说,当你执行一个更新操作后,MySQL会立刻将结果进行提交。

然后开启事务,进行查询修改,最后commit

乐观锁的实现方式主要有两种:CAS机制和版本号机制

版本号机制

版本号机制的基本思路是在数据中增加一个字段version,表示该数据的版本号,每当数据被修改,版本号加1。

  • 当某个线程查询数据时,将该数据的版本号一起查出来;
  • 当该线程更新数据时,判断当前版本号与之前读取的版本号是否一致,如果一致才进行操作。

需要注意的是,这里使用了版本号作为判断数据变化的标记,实际上可以根据实际情况选用其他能够标记数据版本的字段,如时间戳等。

CAS机制

CAS操作包括了3个操作数:

需要读写的内存位置(V)
进行比较的预期值(A)
拟写入的新值(B)

如果内存位置V的值等于预期的A值,则将该位置更新为新值B,否则不进行任何操作。

许多CAS的操作是自旋的:如果操作不成功,会一直重试,直到操作成功为止。

这里引出一个新的问题,既然CAS包含了Compare和Swap两个操作,它又如何保证原子性呢?
答案是:CAS是由CPU支持的原子操作,其原子性是在硬件层面进行保证的。

乐观锁 悲观锁 优缺点和适用场景

  • 功能限制 与悲观锁相比,乐观锁适用的场景受到了更多的限制,无论是CAS还是版本号机制。

  • 竞争激烈程度 如果悲观锁和乐观锁都可以使用,那么选择就要考虑竞争的激烈程度

文章作者: 郭远
本文链接:
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 郭远的博客空间
Java基础 java基础
喜欢就支持一下吧
打赏
微信 微信
支付宝 支付宝