锁,是开发中不得不掌握的一个知识点. 在面试中也会经常问到.其中乐观锁与悲观锁为最常见.首先介绍下两种锁
一:乐观锁:
1 介绍:
它的心态很好,每次别人使用它的时候,它会乐观的认为别人不修改数据,所以不加锁.极大的提高效率.适用于读比较多的场景
2 实现:
常用的实现方式为CAS算法 : compare and swap(比较与交换)
CAS实现是由三个操作数来完成的, 1:读取的变量值 M 2:旧的预期值A 3:新的修改值B (以下简称)
CAS更新条件: 当CAS进行修改操作的时候, 当且仅当M=A,才会把M修改为B,否则什么都不做。(这个可能需要理解CAS的实现步骤,如果不懂建议学习下CAS实现原理).
3 缺点:
鱼和熊掌不可兼得,因为提高了性能,所以安全性肯定有所下降,这就导致一个经典的ABA问题出现了.
4: ABA问题:
CAS修改数据的时候 M初始读取的时候是A值 ,准备修改的时候M=A 符合CAS的条件了.但是这个A值有可能 是特务, 它首先变成了敌人D,然后又变成了友军A. 你说这样它还算是好人吗? 肯定不算. 所以ABA问题就是(A变成B 然后又变成A) . 为了解决这个问题.可以采用加个version版本号来解决.
version版本号:当A每次变换身份的时候,version值+1. 这样M读取A的时候,把版本号也获取,如果A变成特务在变回友军,版本号就会不一致.这个时候就不能修改了. 完美解决特务.
二:悲观锁
1 介绍:
它是一个满满负能量的锁,别人每次使用它,它都会认为别人会修改数据,所以每次都会加锁,性能很低,适用于写比较多的场景
2 实现:
java中的synchronized这种独占锁,就是悲观锁
3 缺点:
悲观锁由于每次使用前都会加锁,就导致在该锁没有被释放之前,是没办法做其他事情的,性能会非常差,java在1.6版本后对 synchronized进行了优化,采用四种级别, (无锁,偏向锁,轻量级锁,重量级锁), 来一步一步的提高锁的级别.
三 两者的使用场景:
CAS适用于写比较少的情况下(多读场景,冲突一般较少),synchronized适用于写比较多的情况下(多写场景,冲突一般较多)