Java 并发编程 —— 悲观锁与乐观锁

39 篇文章 0 订阅
32 篇文章 0 订阅

Java 并发编程 —— 悲观锁与乐观锁

简介

为避免多线程环境下,并发事务造成ACID错误,更合理的使用Spring 事务隔离属性,这篇文章主要介绍如何通过悲观锁与乐观锁来限制Spring事务隔离属性使用不当的问题。

悲观锁

悲观锁(Pessimistic Lock) —— 比较悲观的锁。
认为修改数据时存在着其它连接也想修改此数据的事务。

介绍

  • 悲观锁每次获取数据都要锁数据(共享资源每次只给一个线程使用)
  • 另外的线程获取此数据时是block,直到数据被解锁才可以使用(其它线程阻塞,用完后再把资源转让给其它线程)
  • 常见的悲观锁实现(数据库层面,在以下操作前会锁住数据)
    • 行锁
    • 表锁
    • 读锁
    • 写锁
  • Java(程序层面,重入锁与同步锁都是悲观锁的一种实现)
    • ReentrantLock(重入锁)
    • synchronized(同步锁)

如何使用

数据库行锁
  • FOR UPDATE
# 可在MyBatis使用的时候在SQL中将数据库记录锁住(行锁)
SELECT CLOUMN_A, CLOUMN_B, CLOUMN_C FROM TABLE WHERE CLOUMN_A = 'PARAM_A' FOR UPDATE
# 上面的SQL锁住了TABLE中条件为(CLOUMN_A = 'PARAM_A')的记录。此事务提交前(提交后会释放行锁),其它连接无法使用。
# FOR UPDATE:是行锁的一个关键字,会锁住这张表的这条记录,事务提交之后,才允许其它连接使用。
Hibernate 悲观锁实现
String sql = "SELECT CLOUMN_A, CLOUMN_B, CLOUMN_C FROM TABLE WHERE CLOUMN_A = 'PARAM_A'";
Query query = session.createQuery(sql);
query.setLockMode("SQL_OBJ",LockModel.UPGRADE);

Hibernate 加锁模式

  • Hibernate内部使用使用锁
    • LockMode.NONE
      无锁机制
    • LockMode.WRITE
      Insert和Update记录的时候会自动获取
    • LockMode.READ
      在读取记录时会自动获取
  • 数据库控制锁
    • LockMode.UPGRADE
      利用数据库的for update字句加锁

注意事项

  • 使用悲观锁,必须关闭MySql数据库自动提交属性,MySql默认使用autocommit模式,当执行一个更新操作后,MySql会立刻将结果进行提交。 set autocommit = 0;
  • 使用START TRANSACTION,自动提交将保持禁用状态,直到使用COMMIT或ROLLBACK结束事务。自动提交模式然后恢复到之前的状态(如果start transaction 前 autocommit = 1,则完成本次事务后autocommit 还是1 。 如果start transaction 前 autocommit = 0, 则完成本次事务后 autocommit 还是0)

乐观锁

乐观锁(Optimistic Lock) 每次取数据的时候都认为别人不会修改,所以不锁。
认为在短暂的时间里不会有事务来修改此数据库的数据!

介绍

  • 大多基于数据版本(Version)
  • 数据版本:数据增加一个版本标识,基于数据库表的版本解决方案中,一般是通过为数据表增加一个“version”字段来实现
  • CAS算法实现 (点击打开 Java算法 —— CAS实现)
  • Java 实现
    • java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS实现的。

如何使用

版本标识
  • 读取数据时,读取此数据的版本号
  • 更新时,对此版本号加一
  • 提交对版本数据与数据库表对应记录的当前版本信息进行对比
  • 如果提交的版本号大于数据库当前版本,则更新,否则认为版本过期,事务回滚报错

注意事项

  • 适用于多读应用类型,这样可以提高吞吐量,像数据库提供的类似于write_condition机制,其实都是提供的乐观锁。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值