mysql和java中实现悲观锁和乐观锁

本文介绍了MySQL中乐观锁和悲观锁的实现方法。乐观锁采用数据版本记录机制,通过version字段更新验证数据一致性;悲观锁则利用SQL的for update特性锁定数据,确保事务过程中数据不被其他事务修改。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

mysql乐观锁实现:

 使用数据版本(Version)记录机制实现,这是乐观锁最常用的一种实现方式。何谓数据版本?即为数据增加一个版本标识,一般是通过为数据库表增加一个数字类型的 “version” 字段来实现。当读取数据时,将version字段的值一同读出,数据每更新一次,对此version值加一。当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的version值进行比对,如果数据库表当前版本号与第一次取出来的version值相等,则予以更新,否则认为是过期数据

   1.数据库表设计

     task

   有三个字段,分别是id,value、version

    2.实现

   1)先读task表的数据(实际上这个表只有一条记录),得到version的值为versionValue

   2)每次更新task表中的value字段时,为了防止发生冲突,需要这样操作

      update task set value = newValue,version =  versionValue + 1   where version = versionValue;

      只有这条语句执行了,才表明本次更新value字段的值成功

mysql实现悲观锁

要使用悲观锁,我们必须关闭mysql数据库的自动提交属性,因为MySQL默认使用autocommit模式,也就是说,当你执行一个更新操作后,MySQL会立刻将结果进行提交。

我们可以使用命令设置MySQL为非autocommit模式:

set autocommit=0;

设置完autocommit后,我们就可以执行我们的正常业务了。具体如下:

//0.开始事务

begin;/begin work;/start transaction; (三者选一就可以)

//1.查询出商品信息

select status from t_goods where id=1 for update;

//2.根据商品信息生成订单

insert into t_orders (id,goods_id) values (null,1);

//3.修改商品status为2

update t_goods set status=2 where id = 1;

//4.提交事务

commit;/commit work;

需要注意的是,在事务中,只有SELECT ... FOR UPDATE 或LOCK IN SHARE MODE 同一笔数据时会等待其它事务结束后才执行,一般SELECT ... 则不受此影响。拿上面的实例来说,当我执行select status from t_goods where id=1 for update;后。我在另外的事务中如果再次执行select status from t_goods where id=1 for update;则第二个事务会一直等待第一个事务的提交,此时第二个查询处于阻塞的状态,但是如果我是在第二个事务中执行select status from t_goods where id=1;则能正常查询出数据,不会受第一个事务的影响。

java中乐观锁实现

主要就是两个步骤:冲突检测和数据更新其实现方式有一种比较典型的就是 Compare and Swap ( CAS )。

CAS是乐观锁技术,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。   

    CAS 操作中包含三个操作数 —— 需要读写的内存位置(V)、进行比较的预期原值(A)和拟写入的新值(B)。如果内存位置V的值与预期原值A相匹配,那么处理器会自动将该位置值更新为新值B。否则处理器不做任何操作。无论哪种情况,它都会在 CAS 指令之前返回该位置的值。(在 CAS 的一些特殊情况下将仅返回 CAS 是否成功,而不提取当前值。)CAS 有效地说明了“ 我认为位置 V 应该包含值 A;如果包含该值,则将 B 放到这个位置;否则,不要更改该位置,只告诉我这个位置现在的值即可。 ”这其实和乐观锁的冲突检查+数据更新的原理是一样的。

java中悲观锁的实现

synchronized




### Java悲观锁乐观锁实现机制 #### 悲观锁实现 悲观锁是一种基于锁的并发控制策略,其核心思想是通过加锁的方式确保数据的一致性完整性。在Java中,悲观锁可以通过`java.util.concurrent.locks.Lock`接口或直接使用`synchronized`关键字来实现。 在数据库层面,悲观锁通常通过SQL语句中的`SELECT ... FOR UPDATE`来实现。例如,以下代码展示了如何在MySQL使用悲观锁[^3]: ```sql SELECT * FROM account WHERE id = 1 FOR UPDATE; ``` 上述SQL语句会锁定`account`表中`id=1`的记录,直到当前事务结束。其他事务如果尝试访问或修改这条记录,则会被阻塞。 在Java代码中,可以结合JDBC或ORM框架(如Hibernate)来实现悲观锁。以下是一个简单的示例,展示如何通过Hibernate实现悲观锁: ```java Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); Account account = session.get(Account.class, 1L, LockMode.PESSIMISTIC_WRITE); account.setBalance(account.getBalance() - 100); tx.commit(); session.close(); ``` 上述代码中,`LockMode.PESSIMISTIC_WRITE`用于指定悲观写锁,确保在同一事务内对`account`对象的修改不会与其他事务冲突[^3]。 #### 乐观锁实现 乐观锁假设数据冲突的概率较低,因此在操作时不会加锁,而是在提交更新时检查版本号是否发生变化。如果版本号未变,则允许更新;否则,更新失败并提示用户重试。 在Java中,乐观锁通常通过版本号字段(如`version`)来实现。以下是一个基于MyBatis的乐观锁实现示例[^2]: ```xml <update id="updateAccount" parameterType="Account"> UPDATE account SET balance = #{balance}, version = version + 1 WHERE id = #{id} AND version = #{version} </update> ``` 上述XML映射文件定义了一个更新语句,其中`version = version + 1`表示在更新成功后将版本号递增,而`WHERE id = #{
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值