悲观锁与乐观锁

悲观锁

悲观锁就是我们常说的锁。对于悲观锁来说,它总是认为每次访问共享资源时会发生冲突,所以必须对每次数据操作加上锁,以保证临界区的程序同一时间只能有一个线程在执行。也就是说,共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程。

Java 中的 synchronizeReentrantLock 等独占锁就是悲观锁的具体实现。

高并发的场景下,激烈的锁竞争会造成线程阻塞,大量阻塞线程会导致系统的上下文切换,增加系统的性能开销。并且,悲观锁还可能会存在死锁问题(线程获得锁的顺序不当时),影响代码的正常运行。

悲观锁多用于”写多读少“的环境,避免频繁失败和重试影响性能。

乐观锁

乐观锁又称为“无锁”,乐观锁总是假设对共享资源的访问没有冲突,线程可以不停地执行,无需加锁也无需等待。

而一旦多个线程发生冲突,乐观锁通常是使用一种称为 CAS 的技术来保证线程执行的安全性。

由于无锁操作中没有锁的存在,因此不可能出现死锁的情况,也就是说乐观锁天生免疫死锁

在 Java 中 java.util.concurrent.atomic 包下面的原子变量类(比如 AtomicIntegerLongAdder)就是使用了乐观锁的一种实现方式。

乐观锁多用于“读多写少“的环境,避免频繁加锁影响性能