解释乐观锁和悲观锁的概念,并在 Java 中如何实现这两种锁机制,分别举一个简单的例子?

乐观锁和悲观锁是两种处理并发控制的不同策略,它们各有侧重,适用于不同的场景。下面我会用生活化的例子来帮助你理解这两种锁机制,并展示在Java中如何简单地实现它们。

乐观锁

概念:乐观锁假定在大部分情况下,数据不会发生并发冲突,所以在操作数据前不会加锁,只是在更新数据的时候检查在此期间数据是否被其他事务修改过。乐观锁的核心在于"先做事,后检查"。

例子:想象你和朋友一起去图书馆借书,乐观锁的策略就像是你认为这本书多半没人借,所以你直接去前台登记借书,登记时再确认书有没有被别人借走。如果书被借走了,你就重新找一本或者等待。

Java实现:乐观锁通常借助版本号或时间戳来实现。比如,我们在数据库表中添加一个版本字段version,每次更新数据时,同时更新版本号。

复制代码
1public class Book {
2    private int id;
3    private String title;
4    private int version; // 版本号
5
6    // 更新书籍的方法,使用乐观锁
7    public boolean updateTitle(String newTitle) {
8        // 假设这里有一段SQL,类似 "UPDATE book SET title = ?, version = version + 1 WHERE id = ? AND version = ?"
9        // 如果更新的行数为0,说明版本号不对,即数据已被其他人修改
10        int updatedRows = dao.updateTitleAndVersion(id, newTitle, version);
11        if (updatedRows > 0) {
12            version++; // 如果更新成功,本地版本号也需要+1
13            return true;
14        }
15        return false;
16    }
17}

悲观锁

概念:悲观锁采取较为保守的态度,认为数据在操作过程中很可能会被其他事务修改,因此在操作数据前就会加锁,阻止其他事务的修改操作,直到当前事务完成。悲观锁的核心思想是"先拿锁,后做事"。

例子:还是借书的情景,悲观锁就像是你担心书随时会被别人借走,所以你一开始就拿着这本书去柜台排队,直到借书手续完成才放手,期间别人不能借走这本书。

Java实现:在Java中,悲观锁的实现通常依赖于数据库层面的锁机制,如行级锁。使用JDBC时,可以通过设置事务隔离级别和使用SELECT ... FOR UPDATE来实现悲观锁。

复制代码
1Connection conn = dataSource.getConnection();
2try {
3    conn.setAutoCommit(false); // 开启事务
4    PreparedStatement ps = conn.prepareStatement("SELECT * FROM book WHERE id = ? FOR UPDATE");
5    ps.setInt(1, bookId);
6    ResultSet rs = ps.executeQuery();
7    if (rs.next()) {
8        // 处理数据,比如检查库存、更新信息等
9        // ...
10        
11        // 执行更新操作
12        // ...
13        
14        conn.commit(); // 提交事务
15    }
16} catch (SQLException e) {
17    conn.rollback(); // 出错回滚事务
18} finally {
19    conn.close();
20}
  • 乐观锁适用于并发冲突较少的场景,它通过版本控制减少锁定时间,提高并发性能,但需要额外的逻辑来处理冲突。
  • 悲观锁则适用于并发冲突频繁的场景,它通过提前加锁确保数据一致性,但可能会导致较高的锁竞争和等待时间,影响并发性能。

选择哪种锁,取决于你对数据并发访问的预期和对性能的要求。在实际应用中,还需要根据具体业务场景和数据库特性综合考虑。

相关推荐
Databend19 小时前
如何打造AI时代的数据基石 | Databend Meetup 上海站回顾
数据库
rabbit_pro19 小时前
Java 文件上传到服务器本地存储
java·服务器·python
5***g29819 小时前
Windows安装Rust环境(详细教程)
开发语言·windows·rust
q_191328469519 小时前
基于Springboot2+Vue2的旅游景点购票系统
java·vue.js·spring boot·后端·mysql·毕业设计·计算机毕业设计
XL's妃妃19 小时前
Java 基准测试工具 JMH 详细介绍
java·开发语言·测试工具
Z3r4y19 小时前
【代码审计】RuoYi-4.7.1&4.8.1 Thymeleaf模板注入分析
java·web安全·ruoyi·代码审计·thymeleaf
wudl556619 小时前
向量数据库--FAISS
数据库·faiss
元直数字电路验证19 小时前
Jakarta EE (原 Java EE) 技术栈概览
java·java-ee
冲的运维日常19 小时前
Redis:查看RDB文件内容
数据库·redis·缓存