Java 杂谈

一文简介乐观锁和悲观锁

2019-07-09  本文已影响7人  AcientFish

悲观锁和乐观锁的概念

乐观锁和悲观锁在面试过程中是经常遇到的,那么什么是乐观锁什么是悲观锁呢?首先需要明确的是乐观锁和悲观锁是两种思想,跟编程语言无关,任何语言都有对这两种思想的实现。下面我们来分别谈谈这两种思想。

乐观锁的概念及实现机制

乐观锁是指在操作数据的时候保持乐观态度,即数据不会被别人修改。因此乐观锁有个很明确的特点是乐观锁其实并不加锁。乐观锁只是在修改数据时判断是否在数据获取后到提交修改这期间被别人修改,如果不存在修改则执行自己的操作,否则放弃操作。
乐观锁实现的手段通常有2种,一种是CAS,一种是利用版本号实现。
CAS及Compare And Swap,是一种无锁算法,一般接触CAS是因为i++操作。CAS操作可以保证在无锁状态下i++的原子性。CAS算法主要有3个参数,内存偏移量offset,期望值A和待修改值B。当且仅当offset处的值与A相同时,修改为B,否则不进行任何操作。一般情况下外部会进行自旋不断尝试。
版本号的方式比较容易理解,在数据库种有大量应用,即给数据加上一个version字段,每次操作时判断提取出来的数据版本和此时的版本是否相同,相同则执行操作数据并将version+1,否则不进行操作。

悲观锁的概念及实现机制

悲观锁是指在操作数据的时候持悲观态度,即数据会被他人修改,因此在每次操作前会对数据加锁,直到操作结束时释放锁,在此期间其他人不能操作数据。
悲观锁的实现方式是对代码块加锁(如Synchronized或ReentrantLock等)

优缺点

知道了这两种锁的概念和实现机制后我们来分析分析各自的优缺点,其实两种锁并没有优劣之分,只是看更适合的场景。
由于乐观锁是采用CAS或版本号机制实现,因此存在一些限制,例如

另外版本号机制也存在其他问题,例如

悲观锁由于会对数据加锁,线程获取锁之后其他线程无法获取锁,若操作耗时较长时势必会影响吞吐量。

总结

通过上面的分析可以看出,乐观锁适合读多的场景,而悲观锁适合写多的场景。即对资源竞争激烈的情况下,导致CAS自旋的概率很高,适合使用悲观锁。在资源竞争较少的情况,加锁会浪费CPU资源,而乐观锁可以获得更高的性能。

上一篇 下一篇

猜你喜欢

热点阅读