面试前必须要知道的【乐观锁 悲观锁】
乐观锁、悲观锁是从其使用角度来看。(PS:比如ReentrantLock内部实现用到了CAS和自旋来提高性能,但是从其使用角度来看,是用到了悲观锁的思想。)
1. 乐观锁
乐观锁:顾名思义就是在操作时很乐观,认为操作不会产生并发问题(不会有其他线程对数据进行修改),因此不会上锁。但是在更新时会判断其他线程在这之前有没有对数据进行修改,一般会使用版本号机制或CAS(compare and swap)算法实现。(PS:CAS是原子指令)
简单理解:这里的数据,别想太多,你尽管用,出问题了再修复,即操作失败后事务回滚、提示、更新数据。
原子类的通用实现:
- 声明共享变量为volatile
- 使用CAS的原子更新来实现线程之间的同步
- volatile变量的读/写和CAS所具有的volatile读和写的内存语义来实现线程之间的通信
2. 悲观锁
悲观锁:总是假设最坏的情况,每次取数据时都认为其他线程会修改,所以都会加(悲观)锁。一旦加锁,当不同线程同时执行时,只会有一个线程可以执行,其他的线程在入口处等待,直到锁被释放。
3. 两种锁的使用场景
从上面对两种锁的介绍,我们知道两种锁各有优缺点,不能认为一种好于另一种:
- 乐观锁适用于写比较少的场景下(多读场景),即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果是多写的情况,一般会经常产生冲突,这就会导致上层应用会不断的进行retry,这样反倒是影响了性能
- 悲观锁适用于写比较多的场景下