乐观锁又叫非互斥同步锁,悲观锁又叫互斥同步锁。
悲观锁的劣势
- 阻塞和唤醒带来的性能开销。
- 永久阻塞问题。如果持有锁的线程发生无限循环或者死锁等活跃性的问题,那么等待获取锁执行的线程将无法执行。
- 优先级反转问题。如果我们设置了优先级,当优先级高的线程需要等待优先级低的线程锁的时候,会让线程的优先级反转。
悲观锁概念
持悲观态度,认为每次执行这个同步资源的时候都会有线程争抢这个资源,如果不锁住就会发生错误。所以每次执行时都会锁住,让其他人等待执行完成释放锁后在拿到锁再执行。如synchronized和Lock接口相关类。
乐观锁概念
持乐观态度,认为每次执行这个同步资源的时候都没有线程争抢这个资源。所以执行时不会锁住资源,在更新时会对比我修改期间数据有没有被别人修改过,如果数据与开始一致,证明只有我们自己在操作,就正常修改数据;如果数据与开始不一致,证明有人修改过,那么就不会修改数据,执行放弃、报错、重试等相关策略。如CAS算法实现的相关操作,原子类、并发容器等。git中push操作也是乐观锁,push时如果有人版本号领先我们,则提交失败。
开销对比
- 悲观锁的开销主要是线程阻塞唤醒带来的性能开销。
- 乐观锁的开销主要是线程自旋所带来的cpu性能开销。
使用场景
悲观锁适用于并发写入多的情况,适用于持有锁时间比较长的情况,悲观锁可以避免线程自旋的性能开销。
- 有
IO操作。 - 代码量大,逻辑比较多,相对来说
比较耗时。 并发大,线程竞争激烈。
乐观锁适用于并发写入少,大部分是读取数据的场景。
本文深入探讨了乐观锁和悲观锁的概念,分析了两者的优缺点,包括阻塞和唤醒带来的性能开销、永久阻塞问题、优先级反转问题以及线程自旋的CPU性能开销。并讨论了它们在不同场景下的适用性,如并发写入多或少的情况,以及IO操作和代码量大的场景。
170万+

被折叠的 条评论
为什么被折叠?



