十三、处理并发

1、事务的隔离级别

不考虑隔离级别出现的问题:

脏读:一个线程中的事务读到了另外一个线程中未提交的数据。

不可重复读:一个线程中的事务读到了另外一个线程中提交的update(更新)的数据。

虚读:一个线程中的事务读到了另外一个线程中提交的insert(插入)的数据。

事务的隔离级别:

1:READ UNCOMMITTED:脏读、不可重复读、虚读(幻读)都可能发生。

2:READ COMMITTED:避免脏读;不可重复读、虚读(幻读)都可能发生。

4:REPEATABLE READ:避免脏读、不可重复读,虚读(幻读)可能发生。

8:SERIALIZABLE:避免脏读、不可重复读、虚读(幻读)。

通过配置参数hibernate.connection.isolation=1|2|4|8进行设置。MySQL:默认4  Oracle:默认2

2、第二类更新丢失

 //线程1
@Test
public void test1(){
Session s = HibernateUtil.getSession();
Transaction tx = s.beginTransaction();
Customer c1 = s.get(Customer.class, 1);
c1.setName("泰斯特");
tx.commit();
s.close();
} //线程2
@Test
public void test2(){
Session s = HibernateUtil.getSession();
Transaction tx = s.beginTransaction();
Customer c1 = s.get(Customer.class, 1);
c1.setAge(20);
tx.commit();
s.close();
}

3、解决丢失更新的方案

3.1、悲观锁(不是锁,是一种处理态度。是hibernate的)

Hibernate认为丢失更新现象一定会发生。悲观锁用的是数据库的锁机制。(独占模式效率肯定不会高)

数据库的锁机制:(是真正的锁)

共享锁:可以有多把锁。

MySQL客户端线程1

MySQL客户端线程2

开启事务 strat transaction;

开启事务 strat transaction;

执行查询:select * from customes where id = 1 lock in share mode; 加共享锁

执行查询:select * from customes where id = 1 lock in share mode; 加共享锁

执行更新:update customers set name='张三' where id = 1;

此时会自动加排他锁。但是由于线程2没有释放共享锁,所以线程1处于等待状态。

commit;

当线程2释放共享锁,线程1就可以执行成功了。

排他锁(独占模式,也称为独占锁):只能有一把锁,在锁之前,不能有任何的锁。执行写操作(insert,update,delete)的时候会自动加锁。

MySQL客户端线程1

MySQL客户端线程2

开启事务 strat transaction;

开启事务 strat transaction;

执行查询:select * from customes where id = 1 for update; 加排他锁

执行查询:select * from customes where id = 1 lock in share mode ; 由于有线程1的排他锁存在,线程2将处于等待状态

执行更新:update customers set age = 50 where id = 1;

此时还没有释放排他锁

提交事务(释放排他锁) commit;

线程2显示查询结果,已经是线程1改过之后的数据了。

死锁:DEADLOCK

MySQL客户端线程1

MySQL客户端线程2

开启事务 strat transaction;

开启事务 strat transaction;

执行查询:select * from customes where id = 1 lock in share mode; 加共享锁

执行查询:select * from customes where id = 1 lock in share mode; 加共享锁

执行更新:update customers set name='张三' where id = 1;

此时会自动加排他锁。但是由于线程2没有释放共享锁,所以线程1处于等待状态。

执行更新:update customers set age=18 where id = 1;

此时会自动加排他锁。但是由于线程1没有释放共享锁,所以线程2处于等待状态。

结果:线程1等着线程2释放共享锁,而线程2等着线程1释放排他锁。就造成了死锁。

 //线程1
@Test
public void test1(){
Session s = HibernateUtil.getSession();
Transaction tx = s.beginTransaction();
Customer c1 = s.get(Customer.class, 1,LockMode.PESSIMISTIC_WRITE);//hibernate处理丢失更新的悲观锁解决方式
//Customer c1 = s.get(Customer.class, 1);
c1.setName("泰斯特");
tx.commit();
s.close();
} //线程2
@Test
public void test2(){
Session s = HibernateUtil.getSession();
Transaction tx = s.beginTransaction();
Customer c1 = s.get(Customer.class, 1,LockMode.PESSIMISTIC_WRITE);
//Customer c1 = s.get(Customer.class, 1);
c1.setAge(20);
tx.commit();
s.close();
}

3.2、乐观锁(不是锁,是一种处理态度)

Hibernate认为丢失更新现象不一定会发生。乐观锁使用的是版本号机制。

     private Integer id;
private String name;
private Integer age;
//================版本号==================
private Integer version;
//=======================================
//一对多关系映射:一个客户可以有多个订单
private Set<Order> orders = new HashSet<Order>(0); public Customer(){ }
      <class name="Customer" table="T_CUSTOMERS">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<!-- 版本字段,用于解决丢失更新 -->
<version name="version"></version> <property name="name" column="NAME"></property>
<property name="age" column="AGE"></property>
<!-- 一对多关系映射:
set元素:
作用:映射集合元素
属性:
name:映射实体类中的集合属性
table:指定对应的表
key元素:它是set的子元素
作用:就是用于指定外键的
属性:
column:指定外键字段的名称
one-to-many元素:它是set的子元素
作用:描述当前实体映射文件和set中指定属性之间的关系。
属性:
class:指定是从表的实体类名称
-->
<set name="orders" table="T_ORDERS" >
<key column="CUSTOMER_ID"></key>
<one-to-many class="Order"/>
</set>
</class>

最新文章

  1. 如何在高并发分布式系统中生成全局唯一Id
  2. C#开发微信门户及应用(10)--在管理系统中同步微信用户分组信息
  3. 存储过程 Row_number() 分页
  4. DOM编程 删除节点
  5. 条件注释判断浏览器版本&lt;!--[if lt IE 9]&gt;
  6. mouseover和mouseout多次触发解决方法(兼容ie和firefox)(转)
  7. hdu 1622 Trees on the level
  8. poj 3264 Balanced Lineup(线段树、RMQ)
  9. Oracle Hint用法总结
  10. php下正则表达式整理
  11. c语言输入输出函数
  12. thinkphp框架相关研究(一)
  13. chain pattern
  14. Unity3D ——强大的跨平台3D游戏开发工具(四)
  15. Winform控件根据文字内容自动调整最合适大小
  16. Java课程设计——学生信息系统(团队)
  17. python-简单邮件报警
  18. Spark-shell错误:Missing Python executable &#39;python&#39;, defaulting to ...
  19. python selenium打开新窗口,多窗口切换
  20. [从零开始搭网站八]CentOS使用yum安装Redis的方法

热门文章

  1. position绝对剧中
  2. 【Stage3D学习笔记续】山寨Starling(五):纹理计算和尺寸计算
  3. (10.09作业)学生选课数据库SQL语句练习题
  4. JS单词形式的运算符
  5. 安卓开发21:深入理解Handler
  6. Yale CAS + .net Client 实现 SSO 的完整版
  7. C++ “读取位置 0x****** 时发生访问冲突”的可能原因
  8. Win7家庭普通版、家庭高级版、专业版、旗舰版版本差别
  9. HTML5 面试中最常问到的 10 个问题
  10. JAVA获取CLASSPATH路径--转