悲观锁

悲观锁操作数据时总是担心其它线程也来操作,所以悲观锁在操作时总是上锁,其它线程如果来操作上锁的代码块只能进入阻塞状态。
在 Java 中,synchronized 和 ReentrantLock 都属于悲观锁。
tips: synchronized 关键字在 JDK6 之前是一个重量级的锁,在 JDK6 之后,synchronized 经过各种优化,性能有所提升。

乐观锁

乐观锁与悲观锁相反,它在操作数据时想着别的线程都不会来跟自己竞争,所以在操作的时候都不会上锁,但在最后更新数据的时会判断之前的数据有没有被其它线程修改过,如果修改了,乐观锁会再次尝试,直到数据修改成功。
乐观锁可以使用版本号机制和CAS算法实现。

使用场景

悲观锁适用于多写场景。如果数据失败的代价比较严重,比如银行转账,建议使用悲观锁。
乐观锁适用于多读场景。即冲突较少的时候,使用乐观锁可以提高系统的吞吐量。如果乐观锁用在冲突多的场景,会导致一直循环下去直到操作成功,这反而降低了性能。