讲一讲悲观锁和乐观锁?

有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top

全网最细面试题手册,支持艾宾浩斯记忆法。这是一份最全面、最详细、最高质量的 java面试题,不建议你死记硬背,只要每天复习一遍,有个大概印象就行了。 https://store.amazingmemo.com/chapterDetail/1685324709017001`

悲观锁(Pessimistic Locking)

悲观锁 基于这样一个假设:在多线程的环境下,冲突发生的概率比较高,因此在读取或者写入数据的时候应该先将数据锁定,避免其他线程对数据进行修改,造成数据的不一致。

在Java中,悲观锁 可以通过多种方式实现,比如:

  • Synchronized关键字:这是Java语言内置的同步机制,它可以用于方法级别或者代码块级别。

  • Lock接口:在 java.util.concurrent.locks 包中的 ReentrantLock 类就是一个显式的锁,比较灵活,支持公平锁和非公平锁。

悲观锁的特点是保持数据的严格一致性,但是可能会降低并发效率,因为在等待锁的过程中,其他所有需要访问该数据的线程都会被阻塞。

乐观锁(Optimistic Locking)

与悲观锁不同,乐观锁 是基于这样的假设:多线程并发访问不会总是发生修改,因此不需要通过锁机制来保证数据的一致性,而是采用一种“先做后检查”的方式。

乐观锁通常的实现方式是版本号机制CAS算法(Compare And Swap/Set)。

  • 版本号机制:每次读取数据时,会同时获取一个版本号,并在更新数据时检查这个版本号是否发生变化。如果没有变化,则执行更新;如果已经变化,则说明数据在读取后已经被其他线程修改过,此时可以选择放弃更新或者重试。

  • CAS算法:Java的 java.util.concurrent.atomic 包下面的原子类就是采用CAS算法实现的。这种方法会在数据更新时进行比较并交换,确保数据的一致性。

乐观锁适用于冲突较少的情况,可以提高系统的并发能力。但在冲突较多时,如果大量重试,可能会导致性能下降。

最后更新于