欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 建筑 > 乐观锁和悲观锁(MySQL和Java)

乐观锁和悲观锁(MySQL和Java)

2025/3/10 11:30:19 来源:https://blog.csdn.net/kaka_buka/article/details/140032215  浏览:    关键词:乐观锁和悲观锁(MySQL和Java)

乐观锁和悲观锁(MySQL和Java)

在并发编程中,为了确保数据的一致性和完整性,我们通常需要使用锁机制来控制对共享资源的访问。锁主要分为两种:乐观锁和悲观锁。本文将详细介绍这两种锁的概念、工作原理以及它们的优缺点。

悲观锁

悲观锁(Pessimistic Lock)是一种假定会发生并发冲突的锁机制,因此在操作数据之前,先将数据锁定,以防止其他线程修改数据。这种锁机制通常用于写操作较多的场景,因为它能确保数据的一致性和完整性。

工作原理

当一个线程想要操作某条数据时,它会首先尝试获取该数据的锁。如果获取成功,其他线程将无法对这条数据进行操作,直到该线程释放锁。

优缺点

  • 优点
    • 能够确保数据的强一致性。
    • 简单易用,适用于多写操作的场景。
  • 缺点
    • 可能导致大量的锁竞争,影响性能。
    • 容易引起死锁。

示例

在数据库中,悲观锁通常通过“SELECT … FOR UPDATE”语句来实现。例如:

SELECT * FROM orders WHERE id = 1 FOR UPDATE;

这条语句会在读取数据的同时锁定该行数据,直到事务提交或回滚。

乐观锁

乐观锁(Optimistic Lock)是一种假定不会发生并发冲突的锁机制,它在操作数据时不加锁,而是在提交更新时检查是否有其他线程修改了数据。如果发生冲突,则回滚并重试操作。这种锁机制适用于读操作较多的场景。

工作原理

乐观锁通常通过版本号或时间戳来实现。在更新数据时,检查当前版本号或时间戳是否与读取时一致,如果一致则更新,否则说明数据已被其他线程修改,回滚操作。

优缺点

  • 优点
    • 没有锁竞争,性能较高。
    • 适用于多读操作的场景。
  • 缺点
    • 无法确保数据的强一致性。
    • 需要处理重试逻辑,较为复杂。

示例

在数据库中,乐观锁通常通过版本号来实现。例如:

  1. 查询数据及版本号:
SELECT id, name, version FROM users WHERE id = 1;
  1. 更新数据时,检查版本号:
UPDATE users SET name = 'newName', version = version + 1 WHERE id = 1 AND version = 1;

如果版本号匹配,则更新成功;否则更新失败,需要重试。

Java中的乐观锁和悲观锁

悲观锁

在Java中,悲观锁通常通过synchronized关键字或ReentrantLock类来实现。synchronized关键字可以用来修饰方法或代码块,而ReentrantLock类提供了更灵活的锁控制。

// 使用synchronized关键字
public synchronized void method() {// 临界区代码
}// 使用ReentrantLock
import java.util.concurrent.locks.ReentrantLock;private final ReentrantLock lock = new ReentrantLock();public void method() {lock.lock();try {// 临界区代码} finally {lock.unlock();}
}

乐观锁

在Java中,乐观锁通常通过java.util.concurrent.atomic包中的类来实现,例如AtomicIntegerAtomicLongAtomicReference等。这些类使用CAS(Compare And Swap)操作来实现无锁并发控制。

import java.util.concurrent.atomic.AtomicInteger;private final AtomicInteger version = new AtomicInteger(0);public void update() {int currentVersion = version.get();// 业务逻辑version.compareAndSet(currentVersion, currentVersion + 1);
}

MySQL中的乐观锁和悲观锁

在MySQL中,乐观锁和悲观锁主要通过事务控制和特定的SQL语句来实现。

悲观锁

在MySQL中,可以通过SELECT ... FOR UPDATE语句来实现悲观锁。例如:

START TRANSACTION;
SELECT * FROM orders WHERE id = 1 FOR UPDATE;
-- 执行需要锁定的操作
COMMIT;

乐观锁

乐观锁通常通过版本号或时间戳字段来实现。例如,在更新数据时,可以检查版本号是否一致:

  1. 查询数据及版本号:
SELECT id, name, version FROM users WHERE id = 1;
  1. 更新数据时,检查版本号:
UPDATE users SET name = 'newName', version = version + 1 WHERE id = 1 AND version = 1;

如果版本号匹配,则更新成功;否则更新失败,需要重试。

参考链接

  • MySQL 悲观锁:https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html
  • MySQL 乐观锁:https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html
  • Java并发:https://docs.oracle.com/javase/tutorial/essential/concurrency/

在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词