JAVA并发编程:悲观锁与乐观锁

生活

晴。

悲观与乐观的情绪概念

本篇来了解一下悲观锁和乐观锁,在了解这两个锁之前,我们首先有必要把悲观和乐观这两个词搞清楚:
悲观:对世事怀有消极的看法,认为事物总往糟糕的方向发展。
乐观:对世事怀有积极的态度,认为事物总往好的方向发展。

何为悲观锁

悲观锁:
假定会发生并发的冲突,因此屏蔽一切可能违反数据完整性的操作。
在整个数据处理过程中,锁定要操作的数据。

悲观锁的实现(JAVA/数据库)

悲观锁的实现方式:
JAVA:
synchronized /lock

数据库:
mysql:

select … for update .
如果拿不到锁就等待。

注意:mysql查询扫描到的所有行都会被上行锁,因此mysql在使用悲观锁时务必要用到索引,避免全表扫描,减少扫描行数。

oracle:
select … for update (no wait)
注意:oracle 的悲观锁 有一个no wait 的选项,即当获取不到锁时不等待直接返回。

乐观锁

乐观锁:
假定不会发生并发冲突,因此只在提交数据操作时才执行数据完整性一致性的检查。
乐观锁不能解决脏读。

乐观锁的体现(JAVA/数据库)

乐观锁其实就是通过CAS不断自旋,CAS即compareAndSwap:
执行函数:CAS(V,E,N)
V是要执行的变量,
E是期望值
N是新值。
当E不一致时说明有其他线程修改了该值,那么该线程修改失败,继续CAS。直到成功。

乐观锁的实现:
JAVA:
原子类、AQS

数据库:
SELECT … WHERE version = #version#

使用场景

乐观锁:适用于读多写少的场景。
悲观锁:适用于写多读少的场景。

实际如何选择

需要结合这两种锁的特点,进行合理的选择
-响应速度:选择乐观锁。要么冲突失败要么快速成功。悲观锁则需要等待释放锁才能被执行
-冲突频率:频率高的话不应选择乐观锁,需要重试好几次,代价大。而悲观锁保证成功率
-重试代价:若重试代价大则选择悲观锁

后记

明天看下乐观锁下 CAS的ABA问题~

猜你喜欢

转载自blog.csdn.net/qq_28605513/article/details/84594034