Java 中什么是乐观锁和悲观锁?

· 约 3 分钟读完 · 第 93 / 274 章

推荐答案

在Java中,乐观锁和悲观锁是两种不同的并发控制机制,用于处理多线程环境下的数据一致性问题。

  • 乐观锁:假设并发冲突很少发生,因此在操作数据时不会立即加锁,而是在提交数据时检查是否有冲突。如果没有冲突,操作成功;如果有冲突,操作失败并需要重试。乐观锁通常通过版本号或时间戳来实现。

  • 悲观锁:假设并发冲突经常发生,因此在操作数据时立即加锁,确保在操作完成之前其他线程无法访问该数据。悲观锁通常通过数据库的行锁或表锁来实现。

本题详细解读

乐观锁

乐观锁的核心思想是“先操作,后检查”。它假设在大多数情况下,多个线程不会同时修改同一数据,因此在操作数据时不会立即加锁。乐观锁通常通过以下方式实现:

  1. 版本号机制:在数据表中增加一个版本号字段,每次更新数据时,版本号加1。提交数据时,检查当前版本号是否与读取时的版本号一致,如果一致则更新成功,否则更新失败。

  2. 时间戳机制:与版本号类似,使用时间戳来标记数据的最后修改时间。提交数据时,检查时间戳是否一致。

乐观锁的优点是减少了锁的开销,提高了并发性能。缺点是如果冲突频繁发生,会导致大量的重试操作,降低系统性能。

悲观锁

悲观锁的核心思想是“先加锁,后操作”。它假设在大多数情况下,多个线程会同时修改同一数据,因此在操作数据时立即加锁,确保在操作完成之前其他线程无法访问该数据。悲观锁通常通过以下方式实现:

  1. 数据库行锁:在操作数据时,使用SELECT ... FOR UPDATE语句锁定数据行,确保在事务提交之前其他事务无法修改该行数据。

  2. 表锁:在某些情况下,可能会锁定整个表,以确保数据的一致性。

悲观锁的优点是保证了数据的一致性,缺点是降低了并发性能,因为锁的开销较大。

使用场景

  • 乐观锁适用于读多写少的场景,冲突较少发生的情况下,可以提高系统的并发性能。
  • 悲观锁适用于写多读少的场景,冲突频繁发生的情况下,可以保证数据的一致性。

代码示例

乐观锁示例

悲观锁示例

通过理解乐观锁和悲观锁的区别及其适用场景,可以在实际开发中更好地选择合适的并发控制机制。