解释乐观锁和悲观锁的概念,并在 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}
  • 乐观锁适用于并发冲突较少的场景,它通过版本控制减少锁定时间,提高并发性能,但需要额外的逻辑来处理冲突。
  • 悲观锁则适用于并发冲突频繁的场景,它通过提前加锁确保数据一致性,但可能会导致较高的锁竞争和等待时间,影响并发性能。

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

相关推荐
Maiko Star11 小时前
* SpringBoot整合LangChain4j
java·spring boot·后端·langchain4j
m0_6174939411 小时前
PySide6 数据库操作深度实测:从 SQLite 连接到增删改查避坑指南
jvm·数据库·sqlite
MandalaO_O11 小时前
MyBatis:核心概念 + 环境搭建 + CRUD
java·tomcat·mybatis
吃好睡好便好11 小时前
在Matlab中绘制阶梯图
开发语言·人工智能·学习·算法·机器学习·matlab
Deep-w11 小时前
【MATLAB】基于 MATLAB 的离网光伏储能微电网容量优化仿真研究
开发语言·算法·matlab
诙_12 小时前
由C++速通Lua
开发语言·lua
TechWayfarer12 小时前
AI大模型时代:IP数据云如何适配智能体场景需求
开发语言·人工智能·python·网络协议·tcp/ip·langchain
DN金猿12 小时前
spring.cloud.nacos.discovery.server-addr和spring.cloud.nacos.server-addr区别
java·开发语言·nacos·springcloud·sca
Jasmine_llq12 小时前
《B4261 [GESP202503 三级] 2025》
开发语言·c++·算法·条件判断算法·位运算恒等式推导·简单算术运算
海兰12 小时前
【实用应用】React+TypeScript+Next.js博客项目
开发语言·javascript·elasticsearch