Hbernate:悲观锁与乐观锁

为什么要用锁?

解决并发中出现的问题,解决不可重复读(丢失更新)问题:

事务A在对数据进行操作时,事务B同样在对数据进行操作,在二者操作结束后得到的不是人们所希望的正确的结果

如事务A读取并操作数据,此时读取了商品的库存为20件,取出其中5件,并更新数据。此时更新数据尚未提交,事务B对数据库进行访问,它读取到的库存也为20件,从中取出10件,并先事务A一步提交数据。此时事务A提交数据后,查看数据库发现库存剩余15件,但实际上我们取出了15件商品,事务B对数据库的更新丢失了。这就是丢失更新现象,也称不可重复读。

悲观锁

实现策略

通常依赖于数据库机制,整个过程中将数据锁定,其他任何用户不能读取或修改,适用于短事务的操作。

实际运用

从数据开读取数据时加入LockMode.UPGRADE锁

首先使用load加载数据:

在这里插入图片描述
注意:划线部分中的UPGRADE方法出现了中划线,说明这是一种过时的方法,这种情况一般我们都能在源码中找到代替的方法:

在这里插入图片描述
注释中给出了用来代替此方法的方法:PESSIMISTIC_WRITE

继续代码执行到断点处,我们查看执行日志

在这里插入图片描述
我们明明使用的是load进行懒加载,但Hibernate还是发送了sql语句向数据库中查找数据。这说明,悲观锁不支持懒加载

此时我们模拟多线程并发的情景,直接运行testLoad2方法

在这里插入图片描述
只要当前锁没有解开,其他线程就无法对数据进行访问

小结:

  • 使用悲观锁,访问数据库记录时,就给这条记录加锁,只有当前用户才能对数据进行操作,其他用户将无法访问被枷锁的记录;
  • 数据提交,锁开启,记录属于可操作状态;
  • 悲观锁不支持懒加载。

乐观锁

本质上不是锁,是一种冲突检测手段,其并发性好

使用策略

一般是在数据库表中加入一个version字段,读取数据时将版本号一同读出,之后更新数据时版本号加一。如果提交数据时版本号与数据表中的版本号不符,则认为数据是过期的,否则给予更新。

实际运用

定义实体类
在这里插入图片描述
在实体类中额外增加一个整型属性。

定义hbm.xml映射文件

在这里插入图片描述

  • 在class标签中增加optimistic-lock关键字,将version字段作为乐观锁字段;
  • 使用version标签增加一个字段,映射整型的属性,映射成版本字段,Hibernate将这个版本字段作为乐观锁的控制机制。

创建表:

Hibernate: create table t_inventory (itemNo integer not null auto_increment, version integer not null, itemName varchar(255), quantity integer, primary key (itemNo)) engine=MyISAM

在这里插入图片描述
通过表的结构,我们看到版本字段version是不能为null的

在这里插入图片描述
表中的初始版本号,也就是当前版本号为1

使用懒加载load加载数据:

在这里插入图片描述
查看执行日志

在这里插入图片描述
Hibernate没有发送sql语句,将断点下移

在这里插入图片描述
当需要使用数据时,Hibernate才发送sql语句访问数据库,这说明乐观锁是支持懒加载的

同样,我们模拟多线程并行情景,调用testLoad2:

在这里插入图片描述
执行并查看执行结果:

在这里插入图片描述
我们看到两个方法拿到的版本号都为0,此时,testLoad2方法已经对数据进行了更新,我们将testLoad1方法断点下移,执行commit:

在这里插入图片描述
一执行commit立刻出现了OptimisticLockException异常

在这里插入图片描述
数据库中版本号增加一位。

小结:

  • 乐观锁允许多个线程同时运行;
  • 只要其中一个用户一旦执行commit,通过版本号成功更新后,版本号自增1位;
  • 如果其他用户更新时依旧使用旧版本号更新,这时抛出异常,其他用户就成了过期用户;

乐观锁在时间戳中应用

  • 实体类中添加时间属性;
  • 将时间作为乐观锁的控制字段;
  • 设定的时间作为初始时间;
  • 更新数据时,将初始时间改为当前时间;
  • 其他用户还是用初始时间更新数据时,就会出现错误,其他用户就成了过期用户。

乐观锁和悲观锁的区别:

使用悲观锁时,线程必须串行,其他进程处于等待状态;
使用乐观锁时,线程可以并发运行,但程序可能直接产生异常;

为了保证程序的健壮性,一般情况下使用悲观锁,不使用乐观锁。

说明:本文仅用作学习笔记,无其他用途,如有冒犯可联系本人删除

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值