Java 说一下乐观锁和悲观锁?
乐观锁和悲观锁是并发控制中两种不同的思想和实现方式。
-
悲观锁:
- 思想: 假设在并发情况下会发生冲突,因此在整个操作过程中都认为会有其他事务来修改数据,因此在数据操作之前先加锁,确保自己操作时不会被其他事务干扰。
- 实现方式: 使用数据库的行级锁(例如
SELECT ... FOR UPDATE
)或使用 Java 中的同步锁(例如synchronized
关键字)来保证数据的一致性。 - 示例代码: 使用数据库行级锁的悲观锁。
// 使用 SELECT ... FOR UPDATE 加行级锁 Connection connection = dataSource.getConnection(); connection.setAutoCommit(false); try { PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM my_table WHERE id = ? FOR UPDATE"); preparedStatement.setInt(1, desiredId); ResultSet resultSet = preparedStatement.executeQuery(); // 进行数据更新操作 connection.commit(); } catch (SQLException e) { connection.rollback(); } finally { connection.setAutoCommit(true); connection.close(); }
-
乐观锁:
- 思想: 假设在并发情况下不会发生冲突,因此在整个操作过程中都不加锁,只在更新数据时检查在此期间是否有其他事务对数据进行了修改,如果有则取消操作,重新尝试。
- 实现方式: 使用版本号(或时间戳)进行标记,在更新数据时检查版本号,如果版本号不一致则认为数据已被其他事务修改。
- 示例代码: 使用版本号的乐观锁。
// 数据库表结构包含 version 字段 CREATE TABLE my_table ( id INT PRIMARY KEY, name VARCHAR(50), version INT ); // Java 代码中使用版本号进行乐观锁 Connection connection = dataSource.getConnection(); connection.setAutoCommit(false); try { PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM my_table WHERE id = ?"); preparedStatement.setInt(1, desiredId); ResultSet resultSet = preparedStatement.executeQuery(); // 获取数据并检查版本号 if (resultSet.next()) { int currentVersion = resultSet.getInt("version"); // 进行数据更新操作,更新时同时更新版本号 PreparedStatement updateStatement = connection.prepareStatement("UPDATE my_table SET name = ?, version = ? WHERE id = ? AND version = ?"); updateStatement.setString(1, newName); updateStatement.setInt(2, currentVersion + 1); updateStatement.setInt(3, desiredId); updateStatement.setInt(4, currentVersion); int updatedRows = updateStatement.executeUpdate(); if (updatedRows == 0) { // 更新失败,可能有其他事务修改了数据,可以进行回滚或重试 } } connection.commit(); } catch (SQLException e) { connection.rollback(); } finally { connection.setAutoCommit(true); connection.close(); }
在实际应用中,选择悲观锁还是乐观锁取决于应用的并发访问模式、性能要求以及业务逻辑的复杂性。乐观锁通常在读多写少的场景中表现较好,而悲观锁适用于写多读少、事务较为复杂的场景。