Mysql锁机制--乐观锁 & 悲观锁
===============
从 这篇 文章中,我们知道 Mysql 并发事务会引起更新丢失问题,解决办法是锁。所以本文将对锁(乐观锁、悲观锁)进行分析。
第一部分 悲观锁
1 概念(来自百科)
悲观锁,正如其名,它指的是对数据被外界(包括当前系统的其它事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排它性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。
还可以简单理解,就是Java中的 Synchronized 关键字。只要对代码加了 Synchronized 关键字,JVM 底层就能保证其线程安全性。
那么,在 Mysql 中如何实现悲观锁呢?下面分别以命令行以及Java代码的方式进行演示。
2 命令行演示
2.1 准备数据
DROP DATABASE IF EXISTS cyhTest;
CREATE DATABASE cyhTest; USE cyhTest; DROP TABLE IF EXISTS employee; CREATE TABLE IF NOT EXISTS employee (
id INTEGER NOT NULL,
money INTEGER,
version INTEGER,
PRIMARY KEY (id)
)
ENGINE = INNODB; INSERT INTO employee VALUE (1, 0, 1); SELECT * FROM employee;
目前数据库中只有一条记录,且初始Money=0
2.2 测试
测试准备:
- 还是两个会话(终端),左边会话是白色背景、右边会话是黑色背景
- 关闭自动提交:set autocommit = 0;
现在开始测试:
第一步:两个终端均关闭自动提交
左边:
右边:
第二步:左边利用 select .... for update 的悲观锁语法锁住记录
select * from employee where id = 1 for update;
第三步:右边也尝试利用 select .... for update 的悲观锁语法锁住记录
可以看到,Sql语句被挂起(被阻塞)!
提示:如果被阻塞的时间太长,会提示如下:
第四步:左边执行更新操作并提交事务
Sql语句:
update employee set money = 0 + 1 where id = 1;
commit;
结果:
分析:
- Money 的旧值为0,所以更新时 Money=0+1
- 一执行 commit 后,注意查看右边Sql语句的变化
第五步:查看右边Sql语句的变化
分析:
- 被左边悲观锁阻塞了 11.33 秒
- Money=1,这是左边更新后的结果
2.3 结论
可以看到,当左边(事务A)使用了 select ... for update 的悲观锁后,右边(事务B)再想使用将被阻塞,同时,阻塞被解除后事务B能看到事务A对数据的修改,所以,这就可以很好地解决并发事务的更新丢失问题啦(诚然,这也是人家悲观锁的分内事)
3 Java代码演示
Demo 代码地址:https://github.com/cyhbyw/cyh_Spring_IsolationConcurrencyTransaction
Demo 工程名称:usingMybatis
3.1 准备
确保数据库用户名和密码对应;执行 test.sql 文件中的脚本;
3.2 业务逻辑代码
XML 文件中的 Mapper:
<select id="findByIdWithPessimisticLock" resultType="com.cyh.entity.Employee">
SELECT * FROM employee WHERE id = #{id} FOR UPDATE
</select>
提示:这里是 SELCT ... FOR UPDATE
Service 中的业务逻辑:
@Transactional(rollbackFor = RuntimeException.class)
public void increaseMoneyWithPessimisticLock(Integer id) {
Employee employee = employeeMapper.findByIdWithPessimisticLock(id);
final Integer oldMoney = employee.getMoney();
LOGGER.info("oldMoney: {}", oldMoney);
employee.setMoney(oldMoney + 1);
employeeMapper.updateEmployee(employee);
}
提示:第3行中的 findByIdWithPessimisticLock() 方法就对应上面XML文件中的Mapper,有悲观锁
3.3 测试代码
private void increaseMoneyWithPessimisticLock() {
int threadCount = 100;
while (threadCount-- > 0) {
new Thread(() -> employeeService.increaseMoneyWithPessimisticLock(1)).start();
}
}
提示:100根线程,每个线程将Money值加1,预期结果是100
3.4 执行测试&查看结果
SELECT * FROM employee;
Money=100,是预期结果。
3.5 查看日志
2018-04-25 15:12:14,335 INFO [Thread-5] (EmployeeService.java:36) - oldMoney: 0
2018-04-25 15:12:14,343 INFO [Thread-25] (EmployeeService.java:36) - oldMoney: 1
2018-04-25 15:12:14,345 INFO [Thread-27] (EmployeeService.java:36) - oldMoney: 2
2018-04-25 15:12:14,347 INFO [Thread-23] (EmployeeService.java:36) - oldMoney: 3
2018-04-25 15:12:14,349 INFO [Thread-13] (EmployeeService.java:36) - oldMoney: 4
2018-04-25 15:12:14,350 INFO [Thread-38] (EmployeeService.java:36) - oldMoney: 5
2018-04-25 15:12:14,351 INFO [Thread-24] (EmployeeService.java:36) - oldMoney: 6
2018-04-25 15:12:14,353 INFO [Thread-4] (EmployeeService.java:36) - oldMoney: 7
2018-04-25 15:12:14,355 INFO [Thread-26] (EmployeeService.java:36) - oldMoney: 8
2018-04-25 15:12:14,357 INFO [Thread-8] (EmployeeService.java:36) - oldMoney: 9
2018-04-25 15:12:14,360 INFO [Thread-3] (EmployeeService.java:36) - oldMoney: 10
2018-04-25 15:12:14,361 INFO [Thread-81] (EmployeeService.java:36) - oldMoney: 11
2018-04-25 15:12:14,363 INFO [Thread-20] (EmployeeService.java:36) - oldMoney: 12
2018-04-25 15:12:14,365 INFO [Thread-40] (EmployeeService.java:36) - oldMoney: 13
2018-04-25 15:12:14,366 INFO [Thread-29] (EmployeeService.java:36) - oldMoney: 14
2018-04-25 15:12:14,453 INFO [Thread-14] (EmployeeService.java:36) - oldMoney: 15
2018-04-25 15:12:14,475 INFO [Thread-7] (EmployeeService.java:36) - oldMoney: 16
2018-04-25 15:12:14,485 INFO [Thread-11] (EmployeeService.java:36) - oldMoney: 17
2018-04-25 15:12:14,488 INFO [Thread-48] (EmployeeService.java:36) - oldMoney: 18
2018-04-25 15:12:14,491 INFO [Thread-47] (EmployeeService.java:36) - oldMoney: 19
2018-04-25 15:12:14,494 INFO [Thread-12] (EmployeeService.java:36) - oldMoney: 20
2018-04-25 15:12:14,497 INFO [Thread-72] (EmployeeService.java:36) - oldMoney: 21
2018-04-25 15:12:14,500 INFO [Thread-46] (EmployeeService.java:36) - oldMoney: 22
2018-04-25 15:12:14,501 INFO [Thread-44] (EmployeeService.java:36) - oldMoney: 23
2018-04-25 15:12:14,503 INFO [Thread-45] (EmployeeService.java:36) - oldMoney: 24
2018-04-25 15:12:14,504 INFO [Thread-41] (EmployeeService.java:36) - oldMoney: 25
2018-04-25 15:12:14,505 INFO [Thread-9] (EmployeeService.java:36) - oldMoney: 26
2018-04-25 15:12:14,507 INFO [Thread-19] (EmployeeService.java:36) - oldMoney: 27
2018-04-25 15:12:14,508 INFO [Thread-55] (EmployeeService.java:36) - oldMoney: 28
2018-04-25 15:12:14,509 INFO [Thread-36] (EmployeeService.java:36) - oldMoney: 29
2018-04-25 15:12:14,518 INFO [Thread-43] (EmployeeService.java:36) - oldMoney: 30
2018-04-25 15:12:14,547 INFO [Thread-53] (EmployeeService.java:36) - oldMoney: 31
2018-04-25 15:12:14,556 INFO [Thread-52] (EmployeeService.java:36) - oldMoney: 32
2018-04-25 15:12:14,558 INFO [Thread-51] (EmployeeService.java:36) - oldMoney: 33
2018-04-25 15:12:14,560 INFO [Thread-50] (EmployeeService.java:36) - oldMoney: 34
2018-04-25 15:12:14,562 INFO [Thread-32] (EmployeeService.java:36) - oldMoney: 35
2018-04-25 15:12:14,563 INFO [Thread-85] (EmployeeService.java:36) - oldMoney: 36
2018-04-25 15:12:14,565 INFO [Thread-84] (EmployeeService.java:36) - oldMoney: 37
2018-04-25 15:12:14,567 INFO [Thread-33] (EmployeeService.java:36) - oldMoney: 38
2018-04-25 15:12:14,568 INFO [Thread-82] (EmployeeService.java:36) - oldMoney: 39
2018-04-25 15:12:14,570 INFO [Thread-34] (EmployeeService.java:36) - oldMoney: 40
2018-04-25 15:12:14,571 INFO [Thread-35] (EmployeeService.java:36) - oldMoney: 41
2018-04-25 15:12:14,573 INFO [Thread-83] (EmployeeService.java:36) - oldMoney: 42
2018-04-25 15:12:14,574 INFO [Thread-42] (EmployeeService.java:36) - oldMoney: 43
2018-04-25 15:12:14,575 INFO [Thread-22] (EmployeeService.java:36) - oldMoney: 44
2018-04-25 15:12:14,585 INFO [Thread-30] (EmployeeService.java:36) - oldMoney: 45
2018-04-25 15:12:14,586 INFO [Thread-28] (EmployeeService.java:36) - oldMoney: 46
2018-04-25 15:12:14,613 INFO [Thread-16] (EmployeeService.java:36) - oldMoney: 47
2018-04-25 15:12:14,615 INFO [Thread-17] (EmployeeService.java:36) - oldMoney: 48
2018-04-25 15:12:14,616 INFO [Thread-21] (EmployeeService.java:36) - oldMoney: 49
2018-04-25 15:12:14,618 INFO [Thread-18] (EmployeeService.java:36) - oldMoney: 50
2018-04-25 15:12:14,619 INFO [Thread-37] (EmployeeService.java:36) - oldMoney: 51
2018-04-25 15:12:14,621 INFO [Thread-39] (EmployeeService.java:36) - oldMoney: 52
2018-04-25 15:12:14,623 INFO [Thread-2] (EmployeeService.java:36) - oldMoney: 53
2018-04-25 15:12:14,624 INFO [Thread-1] (EmployeeService.java:36) - oldMoney: 54
2018-04-25 15:12:14,626 INFO [Thread-10] (EmployeeService.java:36) - oldMoney: 55
2018-04-25 15:12:14,627 INFO [Thread-15] (EmployeeService.java:36) - oldMoney: 56
2018-04-25 15:12:14,628 INFO [Thread-56] (EmployeeService.java:36) - oldMoney: 57
2018-04-25 15:12:14,630 INFO [Thread-54] (EmployeeService.java:36) - oldMoney: 58
2018-04-25 15:12:14,632 INFO [Thread-31] (EmployeeService.java:36) - oldMoney: 59
2018-04-25 15:12:14,642 INFO [Thread-57] (EmployeeService.java:36) - oldMoney: 60
2018-04-25 15:12:14,645 INFO [Thread-6] (EmployeeService.java:36) - oldMoney: 61
2018-04-25 15:12:14,672 INFO [Thread-62] (EmployeeService.java:36) - oldMoney: 62
2018-04-25 15:12:14,677 INFO [Thread-59] (EmployeeService.java:36) - oldMoney: 63
2018-04-25 15:12:14,679 INFO [Thread-61] (EmployeeService.java:36) - oldMoney: 64
2018-04-25 15:12:14,680 INFO [Thread-58] (EmployeeService.java:36) - oldMoney: 65
2018-04-25 15:12:14,681 INFO [Thread-80] (EmployeeService.java:36) - oldMoney: 66
2018-04-25 15:12:14,682 INFO [Thread-76] (EmployeeService.java:36) - oldMoney: 67
2018-04-25 15:12:14,684 INFO [Thread-78] (EmployeeService.java:36) - oldMoney: 68
2018-04-25 15:12:14,685 INFO [Thread-100] (EmployeeService.java:36) - oldMoney: 69
2018-04-25 15:12:14,686 INFO [Thread-99] (EmployeeService.java:36) - oldMoney: 70
2018-04-25 15:12:14,688 INFO [Thread-79] (EmployeeService.java:36) - oldMoney: 71
2018-04-25 15:12:14,689 INFO [Thread-94] (EmployeeService.java:36) - oldMoney: 72
2018-04-25 15:12:14,690 INFO [Thread-60] (EmployeeService.java:36) - oldMoney: 73
2018-04-25 15:12:14,691 INFO [Thread-77] (EmployeeService.java:36) - oldMoney: 74
2018-04-25 15:12:14,709 INFO [Thread-95] (EmployeeService.java:36) - oldMoney: 75
2018-04-25 15:12:14,711 INFO [Thread-96] (EmployeeService.java:36) - oldMoney: 76
2018-04-25 15:12:14,712 INFO [Thread-98] (EmployeeService.java:36) - oldMoney: 77
2018-04-25 15:12:14,738 INFO [Thread-75] (EmployeeService.java:36) - oldMoney: 78
2018-04-25 15:12:14,740 INFO [Thread-74] (EmployeeService.java:36) - oldMoney: 79
2018-04-25 15:12:14,741 INFO [Thread-73] (EmployeeService.java:36) - oldMoney: 80
2018-04-25 15:12:14,742 INFO [Thread-71] (EmployeeService.java:36) - oldMoney: 81
2018-04-25 15:12:14,743 INFO [Thread-69] (EmployeeService.java:36) - oldMoney: 82
2018-04-25 15:12:14,745 INFO [Thread-70] (EmployeeService.java:36) - oldMoney: 83
2018-04-25 15:12:14,746 INFO [Thread-68] (EmployeeService.java:36) - oldMoney: 84
2018-04-25 15:12:14,748 INFO [Thread-66] (EmployeeService.java:36) - oldMoney: 85
2018-04-25 15:12:14,749 INFO [Thread-67] (EmployeeService.java:36) - oldMoney: 86
2018-04-25 15:12:14,751 INFO [Thread-64] (EmployeeService.java:36) - oldMoney: 87
2018-04-25 15:12:14,754 INFO [Thread-65] (EmployeeService.java:36) - oldMoney: 88
2018-04-25 15:12:14,755 INFO [Thread-63] (EmployeeService.java:36) - oldMoney: 89
2018-04-25 15:12:14,767 INFO [Thread-97] (EmployeeService.java:36) - oldMoney: 90
2018-04-25 15:12:14,769 INFO [Thread-93] (EmployeeService.java:36) - oldMoney: 91
2018-04-25 15:12:14,770 INFO [Thread-49] (EmployeeService.java:36) - oldMoney: 92
2018-04-25 15:12:14,796 INFO [Thread-92] (EmployeeService.java:36) - oldMoney: 93
2018-04-25 15:12:14,801 INFO [Thread-91] (EmployeeService.java:36) - oldMoney: 94
2018-04-25 15:12:14,803 INFO [Thread-89] (EmployeeService.java:36) - oldMoney: 95
2018-04-25 15:12:14,803 INFO [Thread-90] (EmployeeService.java:36) - oldMoney: 96
2018-04-25 15:12:14,804 INFO [Thread-88] (EmployeeService.java:36) - oldMoney: 97
2018-04-25 15:12:14,806 INFO [Thread-87] (EmployeeService.java:36) - oldMoney: 98
2018-04-25 15:12:14,807 INFO [Thread-86] (EmployeeService.java:36) - oldMoney: 99
可以看到,oldMoney 值由0到99依次严格递增且不重复(这就是想要的效果)。
第二部分 乐观锁
1 概念
1.1 理解方式一(来自网上其它小伙伴的博客)
乐观锁认为一般情况下数据不会造成冲突,所以在数据进行提交更新时才会对数据的冲突与否进行检测。如果没有冲突那就OK;如果出现冲突了,则返回错误信息并让用户决定如何去做。
1.2 理解方式二(来自网上其它小伙伴的博客)
乐观锁的特点是先进行业务操作,不到万不得已不会去拿锁。乐观地认为拿锁多半会是成功的,因此在完成业务操作需要实际更新数据的最后一步再去拿一下锁。
1.3 我的理解
理解一:就是 CAS 操作
理解二:类似于 SVN、GIt 这些版本管理系统,当修改了某个文件需要提交的时候,它会检查文件的当前版本是否与服务器上的一致,如果一致那就可以直接提交,如果不一致,那就必须先更新服务器上的最新代码然后再提交(也就是先将这个文件的版本更新成和服务器一样的版本)
2 如何实现乐观锁呢
首先说明一点的是:乐观锁在数据库上的实现完全是逻辑的,数据库本身不提供支持,而是需要开发者自己来实现。
常见的做法有两种:版本号控制及时间戳控制。
版本号控制的原理:
- 为表中加一个 version 字段;
- 当读取数据时,连同这个 version 字段一起读出;
- 数据每更新一次就将此值加一;
- 当提交更新时,判断数据库表中对应记录的当前版本号是否与之前取出来的版本号一致,如果一致则可以直接更新,如果不一致则表示是过期数据需要重试或者做其它操作(PS:这完完全全就是 CAS 的实现逻辑呀~)
至于时间戳控制,其原理和版本号控制差不多,也是在表中添加一个 timestamp 的时间戳字段,然后提交更新时判断数据库中对应记录的当前时间戳是否与之前取出来的时间戳一致,一致就更新,不一致就重试。
3 Java代码演示
3.1 准备
还是之前的Java代码;这里使用版本号控制来实现乐观锁。
3.2 业务逻辑代码
XMP 文件中的 Mapper:
<update id="updateEmployeeWithOptimisticLock">
UPDATE employee SET money = #{e.money}, version = #{e.version} + 1 WHERE id = #{e.id} AND #{e.version} = version
</update>
提示:
- SET 中有 version = #{e.version} + 1 的操作
- WHERE 条件中有 #{e.version} = version 的判断
Service 中的业务逻辑:
/**
* 失败尝试
* @param id
*/
public void increaseMoneyWithOptimisticLock(Integer id) {
int tryTimes = 0;
while (true) {
tryTimes++;
if (internalIncreaseMoneyWithOptimisticLock(id) != 0) {
// 说明更新成功,直接退出
break;
}
if (tryTimes == 200) {
// 达到最大重试次数,退出
break;
}
try {
// 休息一段时间后再重试
TimeUnit.MILLISECONDS.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
}
LOGGER.info("tryTimes: {}", tryTimes);
} /**
* 查找Employee对象,并进行更新
* @param id
* @return
*/
@Transactional(rollbackFor = RuntimeException.class)
public Integer internalIncreaseMoneyWithOptimisticLock(Integer id) {
Employee employee = employeeMapper.findById(id);
final Integer oldMoney = employee.getMoney();
LOGGER.info("oldMoney: {}", oldMoney);
employee.setMoney(oldMoney + 1);
return employeeMapper.updateEmployeeWithOptimisticLock(employee);
}
提示:
- 乐观锁,其实是开发者自己实现的逻辑
- 更新失败后,休息一段时间后再进行重试
3.3 测试代码
private void increaseMoneyWithOptimisticLock() {
int threadCount = 100;
while (threadCount-- > 0) {
new Thread(() -> employeeService.increaseMoneyWithOptimisticLock(1)).start();
}
}
提示:100根线程,每个线程将Money值加1,预期结果是Money的值在之前的基础上增加100
3.4 执行测试&查看结果
之前Money=100,现在预期增加100,所以现在Money=200符合预期。同时,version 字段的值也由最初的1更新为101(也被更新了100次,每次加一)。
3.5 查看日志
2018-04-25 16:24:07,851 INFO [Thread-36] (EmployeeService.java:77) - oldMoney: 100
2018-04-25 16:24:07,853 INFO [Thread-54] (EmployeeService.java:77) - oldMoney: 100
2018-04-25 16:24:07,856 INFO [Thread-55] (EmployeeService.java:77) - oldMoney: 100
2018-04-25 16:24:07,856 INFO [Thread-45] (EmployeeService.java:77) - oldMoney: 100
2018-04-25 16:24:07,858 INFO [Thread-56] (EmployeeService.java:77) - oldMoney: 100
2018-04-25 16:24:07,858 INFO [Thread-53] (EmployeeService.java:77) - oldMoney: 100
2018-04-25 16:24:07,858 INFO [Thread-33] (EmployeeService.java:77) - oldMoney: 100
2018-04-25 16:24:07,859 INFO [Thread-57] (EmployeeService.java:77) - oldMoney: 100
2018-04-25 16:24:07,859 INFO [Thread-31] (EmployeeService.java:77) - oldMoney: 100
2018-04-25 16:24:07,863 INFO [Thread-30] (EmployeeService.java:77) - oldMoney: 101
2018-04-25 16:24:07,868 INFO [Thread-29] (EmployeeService.java:77) - oldMoney: 101
2018-04-25 16:24:07,880 INFO [Thread-75] (EmployeeService.java:77) - oldMoney: 101
2018-04-25 16:24:07,881 INFO [Thread-76] (EmployeeService.java:77) - oldMoney: 102
2018-04-25 16:24:07,882 INFO [Thread-78] (EmployeeService.java:77) - oldMoney: 102
2018-04-25 16:24:07,883 INFO [Thread-77] (EmployeeService.java:77) - oldMoney: 102
2018-04-25 16:24:07,885 INFO [Thread-79] (EmployeeService.java:77) - oldMoney: 103
2018-04-25 16:24:07,887 INFO [Thread-80] (EmployeeService.java:77) - oldMoney: 103
2018-04-25 16:24:07,888 INFO [Thread-28] (EmployeeService.java:77) - oldMoney: 104
2018-04-25 16:24:07,890 INFO [Thread-27] (EmployeeService.java:77) - oldMoney: 104
2018-04-25 16:24:07,892 INFO [Thread-26] (EmployeeService.java:77) - oldMoney: 105
2018-04-25 16:24:07,894 INFO [Thread-25] (EmployeeService.java:77) - oldMoney: 105
2018-04-25 16:24:07,895 INFO [Thread-24] (EmployeeService.java:77) - oldMoney: 106
2018-04-25 16:24:07,897 INFO [Thread-83] (EmployeeService.java:77) - oldMoney: 106
2018-04-25 16:24:07,898 INFO [Thread-82] (EmployeeService.java:77) - oldMoney: 106
2018-04-25 16:24:07,900 INFO [Thread-84] (EmployeeService.java:77) - oldMoney: 107
2018-04-25 16:24:07,904 INFO [Thread-21] (EmployeeService.java:77) - oldMoney: 108
2018-04-25 16:24:07,906 INFO [Thread-20] (EmployeeService.java:77) - oldMoney: 109
2018-04-25 16:24:07,907 INFO [Thread-6] (EmployeeService.java:77) - oldMoney: 109
2018-04-25 16:24:07,908 INFO [Thread-9] (EmployeeService.java:77) - oldMoney: 110
2018-04-25 16:24:07,909 INFO [Thread-85] (EmployeeService.java:77) - oldMoney: 110
2018-04-25 16:24:07,909 INFO [Thread-86] (EmployeeService.java:77) - oldMoney: 111
2018-04-25 16:24:07,911 INFO [Thread-91] (EmployeeService.java:77) - oldMoney: 111
2018-04-25 16:24:07,912 INFO [Thread-81] (EmployeeService.java:77) - oldMoney: 112
2018-04-25 16:24:07,913 INFO [Thread-90] (EmployeeService.java:77) - oldMoney: 112
2018-04-25 16:24:07,915 INFO [Thread-96] (EmployeeService.java:77) - oldMoney: 112
2018-04-25 16:24:07,924 INFO [Thread-97] (EmployeeService.java:77) - oldMoney: 113
2018-04-25 16:24:07,926 INFO [Thread-36] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:07,928 INFO [Thread-18] (EmployeeService.java:77) - oldMoney: 113
2018-04-25 16:24:07,929 INFO [Thread-4] (EmployeeService.java:77) - oldMoney: 113
2018-04-25 16:24:07,932 INFO [Thread-94] (EmployeeService.java:77) - oldMoney: 114
2018-04-25 16:24:07,934 INFO [Thread-12] (EmployeeService.java:77) - oldMoney: 114
2018-04-25 16:24:07,935 INFO [Thread-93] (EmployeeService.java:77) - oldMoney: 114
2018-04-25 16:24:07,939 INFO [Thread-92] (EmployeeService.java:77) - oldMoney: 115
2018-04-25 16:24:07,940 INFO [Thread-69] (EmployeeService.java:77) - oldMoney: 115
2018-04-25 16:24:07,960 INFO [Thread-86] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:07,961 INFO [Thread-9] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:07,960 INFO [Thread-75] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:07,962 INFO [Thread-33] (EmployeeService.java:77) - oldMoney: 116
2018-04-25 16:24:07,963 INFO [Thread-87] (EmployeeService.java:77) - oldMoney: 116
2018-04-25 16:24:07,963 INFO [Thread-6] (EmployeeService.java:77) - oldMoney: 116
2018-04-25 16:24:07,964 INFO [Thread-20] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:07,964 INFO [Thread-21] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:07,964 INFO [Thread-90] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:07,965 INFO [Thread-26] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:07,965 INFO [Thread-28] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:07,965 INFO [Thread-83] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:07,966 INFO [Thread-76] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:07,966 INFO [Thread-79] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:07,967 INFO [Thread-84] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:07,974 INFO [Thread-16] (EmployeeService.java:77) - oldMoney: 116
2018-04-25 16:24:07,974 INFO [Thread-17] (EmployeeService.java:77) - oldMoney: 116
2018-04-25 16:24:07,974 INFO [Thread-89] (EmployeeService.java:77) - oldMoney: 116
2018-04-25 16:24:07,975 INFO [Thread-13] (EmployeeService.java:77) - oldMoney: 116
2018-04-25 16:24:07,976 INFO [Thread-7] (EmployeeService.java:77) - oldMoney: 116
2018-04-25 16:24:07,976 INFO [Thread-100] (EmployeeService.java:77) - oldMoney: 116
2018-04-25 16:24:07,976 INFO [Thread-95] (EmployeeService.java:77) - oldMoney: 116
2018-04-25 16:24:07,978 INFO [Thread-88] (EmployeeService.java:77) - oldMoney: 116
2018-04-25 16:24:07,978 INFO [Thread-8] (EmployeeService.java:77) - oldMoney: 117
2018-04-25 16:24:07,979 INFO [Thread-11] (EmployeeService.java:77) - oldMoney: 117
2018-04-25 16:24:07,980 INFO [Thread-5] (EmployeeService.java:77) - oldMoney: 118
2018-04-25 16:24:07,980 INFO [Thread-19] (EmployeeService.java:77) - oldMoney: 118
2018-04-25 16:24:07,980 INFO [Thread-22] (EmployeeService.java:77) - oldMoney: 118
2018-04-25 16:24:07,981 INFO [Thread-2] (EmployeeService.java:77) - oldMoney: 119
2018-04-25 16:24:07,981 INFO [Thread-23] (EmployeeService.java:77) - oldMoney: 119
2018-04-25 16:24:07,982 INFO [Thread-35] (EmployeeService.java:77) - oldMoney: 119
2018-04-25 16:24:07,982 INFO [Thread-32] (EmployeeService.java:77) - oldMoney: 119
2018-04-25 16:24:07,983 INFO [Thread-34] (EmployeeService.java:77) - oldMoney: 120
2018-04-25 16:24:07,983 INFO [Thread-37] (EmployeeService.java:77) - oldMoney: 120
2018-04-25 16:24:07,984 INFO [Thread-38] (EmployeeService.java:77) - oldMoney: 120
2018-04-25 16:24:07,985 INFO [Thread-39] (EmployeeService.java:77) - oldMoney: 121
2018-04-25 16:24:07,985 INFO [Thread-40] (EmployeeService.java:77) - oldMoney: 121
2018-04-25 16:24:07,986 INFO [Thread-41] (EmployeeService.java:77) - oldMoney: 121
2018-04-25 16:24:07,986 INFO [Thread-43] (EmployeeService.java:77) - oldMoney: 121
2018-04-25 16:24:07,987 INFO [Thread-44] (EmployeeService.java:77) - oldMoney: 122
2018-04-25 16:24:07,988 INFO [Thread-48] (EmployeeService.java:77) - oldMoney: 122
2018-04-25 16:24:07,988 INFO [Thread-49] (EmployeeService.java:77) - oldMoney: 122
2018-04-25 16:24:07,989 INFO [Thread-50] (EmployeeService.java:77) - oldMoney: 122
2018-04-25 16:24:07,986 INFO [Thread-42] (EmployeeService.java:77) - oldMoney: 121
2018-04-25 16:24:07,990 INFO [Thread-52] (EmployeeService.java:77) - oldMoney: 123
2018-04-25 16:24:07,989 INFO [Thread-51] (EmployeeService.java:77) - oldMoney: 122
2018-04-25 16:24:07,988 INFO [Thread-47] (EmployeeService.java:77) - oldMoney: 122
2018-04-25 16:24:07,987 INFO [Thread-46] (EmployeeService.java:77) - oldMoney: 122
2018-04-25 16:24:07,991 INFO [Thread-60] (EmployeeService.java:77) - oldMoney: 123
2018-04-25 16:24:07,990 INFO [Thread-58] (EmployeeService.java:77) - oldMoney: 123
2018-04-25 16:24:07,992 INFO [Thread-64] (EmployeeService.java:77) - oldMoney: 124
2018-04-25 16:24:07,992 INFO [Thread-65] (EmployeeService.java:77) - oldMoney: 124
2018-04-25 16:24:07,992 INFO [Thread-61] (EmployeeService.java:77) - oldMoney: 124
2018-04-25 16:24:07,993 INFO [Thread-63] (EmployeeService.java:77) - oldMoney: 125
2018-04-25 16:24:07,995 INFO [Thread-68] (EmployeeService.java:77) - oldMoney: 125
2018-04-25 16:24:07,995 INFO [Thread-67] (EmployeeService.java:77) - oldMoney: 125
2018-04-25 16:24:07,995 INFO [Thread-15] (EmployeeService.java:77) - oldMoney: 125
2018-04-25 16:24:07,996 INFO [Thread-66] (EmployeeService.java:77) - oldMoney: 125
2018-04-25 16:24:07,997 INFO [Thread-99] (EmployeeService.java:77) - oldMoney: 126
2018-04-25 16:24:07,998 INFO [Thread-98] (EmployeeService.java:77) - oldMoney: 126
2018-04-25 16:24:07,998 INFO [Thread-74] (EmployeeService.java:77) - oldMoney: 126
2018-04-25 16:24:08,002 INFO [Thread-92] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:08,002 INFO [Thread-73] (EmployeeService.java:77) - oldMoney: 127
2018-04-25 16:24:08,002 INFO [Thread-18] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:08,004 INFO [Thread-62] (EmployeeService.java:77) - oldMoney: 127
2018-04-25 16:24:08,004 INFO [Thread-27] (EmployeeService.java:77) - oldMoney: 127
2018-04-25 16:24:08,005 INFO [Thread-46] (EmployeeService.java:77) - oldMoney: 128
2018-04-25 16:24:08,006 INFO [Thread-59] (EmployeeService.java:77) - oldMoney: 128
2018-04-25 16:24:08,006 INFO [Thread-71] (EmployeeService.java:77) - oldMoney: 128
2018-04-25 16:24:08,006 INFO [Thread-3] (EmployeeService.java:77) - oldMoney: 128
2018-04-25 16:24:08,007 INFO [Thread-56] (EmployeeService.java:77) - oldMoney: 128
2018-04-25 16:24:08,008 INFO [Thread-72] (EmployeeService.java:77) - oldMoney: 128
2018-04-25 16:24:08,008 INFO [Thread-93] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:08,010 INFO [Thread-70] (EmployeeService.java:77) - oldMoney: 129
2018-04-25 16:24:08,010 INFO [Thread-10] (EmployeeService.java:77) - oldMoney: 129
2018-04-25 16:24:08,010 INFO [Thread-17] (EmployeeService.java:77) - oldMoney: 129
2018-04-25 16:24:08,011 INFO [Thread-14] (EmployeeService.java:77) - oldMoney: 129
2018-04-25 16:24:08,012 INFO [Thread-1] (EmployeeService.java:77) - oldMoney: 130
2018-04-25 16:24:08,032 INFO [Thread-5] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:08,032 INFO [Thread-49] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:08,032 INFO [Thread-87] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:08,032 INFO [Thread-64] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:08,032 INFO [Thread-8] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:08,033 INFO [Thread-41] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:08,033 INFO [Thread-52] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:08,034 INFO [Thread-2] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:08,034 INFO [Thread-72] (EmployeeService.java:77) - oldMoney: 131
2018-04-25 16:24:08,035 INFO [Thread-99] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:08,035 INFO [Thread-34] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:08,035 INFO [Thread-68] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:08,037 INFO [Thread-30] (EmployeeService.java:77) - oldMoney: 131
2018-04-25 16:24:08,049 INFO [Thread-30] (EmployeeService.java:77) - oldMoney: 132
2018-04-25 16:24:08,068 INFO [Thread-3] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:08,068 INFO [Thread-10] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:08,068 INFO [Thread-73] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:08,068 INFO [Thread-1] (EmployeeService.java:65) - tryTimes: 1
2018-04-25 16:24:08,070 INFO [Thread-24] (EmployeeService.java:77) - oldMoney: 133
2018-04-25 16:24:08,082 INFO [Thread-69] (EmployeeService.java:77) - oldMoney: 134
2018-04-25 16:24:08,087 INFO [Thread-60] (EmployeeService.java:77) - oldMoney: 135
2018-04-25 16:24:08,117 INFO [Thread-38] (EmployeeService.java:77) - oldMoney: 136
2018-04-25 16:24:08,125 INFO [Thread-46] (EmployeeService.java:77) - oldMoney: 137
2018-04-25 16:24:08,131 INFO [Thread-30] (EmployeeService.java:65) - tryTimes: 3
2018-04-25 16:24:08,132 INFO [Thread-72] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,149 INFO [Thread-11] (EmployeeService.java:77) - oldMoney: 138
2018-04-25 16:24:08,170 INFO [Thread-98] (EmployeeService.java:77) - oldMoney: 139
2018-04-25 16:24:08,180 INFO [Thread-60] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,181 INFO [Thread-46] (EmployeeService.java:65) - tryTimes: 3
2018-04-25 16:24:08,180 INFO [Thread-69] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,180 INFO [Thread-38] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,180 INFO [Thread-24] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,188 INFO [Thread-71] (EmployeeService.java:77) - oldMoney: 140
2018-04-25 16:24:08,204 INFO [Thread-96] (EmployeeService.java:77) - oldMoney: 141
2018-04-25 16:24:08,210 INFO [Thread-11] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,210 INFO [Thread-98] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,230 INFO [Thread-91] (EmployeeService.java:77) - oldMoney: 142
2018-04-25 16:24:08,239 INFO [Thread-71] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,239 INFO [Thread-96] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,254 INFO [Thread-25] (EmployeeService.java:77) - oldMoney: 143
2018-04-25 16:24:08,254 INFO [Thread-58] (EmployeeService.java:77) - oldMoney: 143
2018-04-25 16:24:08,263 INFO [Thread-17] (EmployeeService.java:77) - oldMoney: 144
2018-04-25 16:24:08,268 INFO [Thread-91] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,275 INFO [Thread-63] (EmployeeService.java:77) - oldMoney: 145
2018-04-25 16:24:08,275 INFO [Thread-89] (EmployeeService.java:77) - oldMoney: 145
2018-04-25 16:24:08,277 INFO [Thread-51] (EmployeeService.java:77) - oldMoney: 146
2018-04-25 16:24:08,279 INFO [Thread-56] (EmployeeService.java:77) - oldMoney: 147
2018-04-25 16:24:08,280 INFO [Thread-40] (EmployeeService.java:77) - oldMoney: 147
2018-04-25 16:24:08,280 INFO [Thread-65] (EmployeeService.java:77) - oldMoney: 147
2018-04-25 16:24:08,287 INFO [Thread-100] (EmployeeService.java:77) - oldMoney: 148
2018-04-25 16:24:08,298 INFO [Thread-25] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,299 INFO [Thread-17] (EmployeeService.java:65) - tryTimes: 3
2018-04-25 16:24:08,310 INFO [Thread-47] (EmployeeService.java:77) - oldMoney: 149
2018-04-25 16:24:08,319 INFO [Thread-6] (EmployeeService.java:77) - oldMoney: 150
2018-04-25 16:24:08,327 INFO [Thread-100] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,327 INFO [Thread-56] (EmployeeService.java:65) - tryTimes: 3
2018-04-25 16:24:08,327 INFO [Thread-63] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,328 INFO [Thread-51] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,364 INFO [Thread-6] (EmployeeService.java:65) - tryTimes: 3
2018-04-25 16:24:08,365 INFO [Thread-47] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,388 INFO [Thread-33] (EmployeeService.java:77) - oldMoney: 151
2018-04-25 16:24:08,400 INFO [Thread-58] (EmployeeService.java:77) - oldMoney: 152
2018-04-25 16:24:08,404 INFO [Thread-35] (EmployeeService.java:77) - oldMoney: 153
2018-04-25 16:24:08,424 INFO [Thread-89] (EmployeeService.java:77) - oldMoney: 154
2018-04-25 16:24:08,427 INFO [Thread-33] (EmployeeService.java:65) - tryTimes: 3
2018-04-25 16:24:08,431 INFO [Thread-88] (EmployeeService.java:77) - oldMoney: 155
2018-04-25 16:24:08,453 INFO [Thread-12] (EmployeeService.java:77) - oldMoney: 156
2018-04-25 16:24:08,454 INFO [Thread-70] (EmployeeService.java:77) - oldMoney: 157
2018-04-25 16:24:08,457 INFO [Thread-89] (EmployeeService.java:65) - tryTimes: 3
2018-04-25 16:24:08,457 INFO [Thread-58] (EmployeeService.java:65) - tryTimes: 3
2018-04-25 16:24:08,458 INFO [Thread-35] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,459 INFO [Thread-54] (EmployeeService.java:77) - oldMoney: 158
2018-04-25 16:24:08,461 INFO [Thread-67] (EmployeeService.java:77) - oldMoney: 159
2018-04-25 16:24:08,470 INFO [Thread-31] (EmployeeService.java:77) - oldMoney: 160
2018-04-25 16:24:08,485 INFO [Thread-12] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,485 INFO [Thread-70] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,486 INFO [Thread-88] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,488 INFO [Thread-81] (EmployeeService.java:77) - oldMoney: 161
2018-04-25 16:24:08,497 INFO [Thread-23] (EmployeeService.java:77) - oldMoney: 162
2018-04-25 16:24:08,504 INFO [Thread-82] (EmployeeService.java:77) - oldMoney: 163
2018-04-25 16:24:08,507 INFO [Thread-50] (EmployeeService.java:77) - oldMoney: 164
2018-04-25 16:24:08,510 INFO [Thread-78] (EmployeeService.java:77) - oldMoney: 165
2018-04-25 16:24:08,514 INFO [Thread-67] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,514 INFO [Thread-54] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,516 INFO [Thread-97] (EmployeeService.java:77) - oldMoney: 166
2018-04-25 16:24:08,517 INFO [Thread-31] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,534 INFO [Thread-61] (EmployeeService.java:77) - oldMoney: 167
2018-04-25 16:24:08,538 INFO [Thread-29] (EmployeeService.java:77) - oldMoney: 168
2018-04-25 16:24:08,543 INFO [Thread-23] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,544 INFO [Thread-81] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,544 INFO [Thread-50] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,543 INFO [Thread-82] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,544 INFO [Thread-78] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,556 INFO [Thread-74] (EmployeeService.java:77) - oldMoney: 169
2018-04-25 16:24:08,572 INFO [Thread-61] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,573 INFO [Thread-29] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,572 INFO [Thread-97] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,582 INFO [Thread-80] (EmployeeService.java:77) - oldMoney: 170
2018-04-25 16:24:08,583 INFO [Thread-48] (EmployeeService.java:77) - oldMoney: 171
2018-04-25 16:24:08,584 INFO [Thread-27] (EmployeeService.java:77) - oldMoney: 172
2018-04-25 16:24:08,589 INFO [Thread-32] (EmployeeService.java:77) - oldMoney: 173
2018-04-25 16:24:08,602 INFO [Thread-74] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,608 INFO [Thread-85] (EmployeeService.java:77) - oldMoney: 174
2018-04-25 16:24:08,631 INFO [Thread-32] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,631 INFO [Thread-27] (EmployeeService.java:65) - tryTimes: 3
2018-04-25 16:24:08,631 INFO [Thread-80] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,632 INFO [Thread-48] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,634 INFO [Thread-22] (EmployeeService.java:77) - oldMoney: 175
2018-04-25 16:24:08,660 INFO [Thread-85] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,689 INFO [Thread-22] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,696 INFO [Thread-44] (EmployeeService.java:77) - oldMoney: 176
2018-04-25 16:24:08,696 INFO [Thread-43] (EmployeeService.java:77) - oldMoney: 176
2018-04-25 16:24:08,704 INFO [Thread-13] (EmployeeService.java:77) - oldMoney: 177
2018-04-25 16:24:08,712 INFO [Thread-4] (EmployeeService.java:77) - oldMoney: 178
2018-04-25 16:24:08,722 INFO [Thread-45] (EmployeeService.java:77) - oldMoney: 179
2018-04-25 16:24:08,723 INFO [Thread-7] (EmployeeService.java:77) - oldMoney: 179
2018-04-25 16:24:08,727 INFO [Thread-44] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,743 INFO [Thread-77] (EmployeeService.java:77) - oldMoney: 180
2018-04-25 16:24:08,748 INFO [Thread-59] (EmployeeService.java:77) - oldMoney: 181
2018-04-25 16:24:08,754 INFO [Thread-57] (EmployeeService.java:77) - oldMoney: 182
2018-04-25 16:24:08,756 INFO [Thread-45] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,756 INFO [Thread-13] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,757 INFO [Thread-4] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,765 INFO [Thread-39] (EmployeeService.java:77) - oldMoney: 183
2018-04-25 16:24:08,779 INFO [Thread-66] (EmployeeService.java:77) - oldMoney: 184
2018-04-25 16:24:08,785 INFO [Thread-59] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,785 INFO [Thread-77] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,796 INFO [Thread-55] (EmployeeService.java:77) - oldMoney: 185
2018-04-25 16:24:08,811 INFO [Thread-62] (EmployeeService.java:77) - oldMoney: 186
2018-04-25 16:24:08,814 INFO [Thread-39] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,814 INFO [Thread-57] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,814 INFO [Thread-66] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,827 INFO [Thread-94] (EmployeeService.java:77) - oldMoney: 187
2018-04-25 16:24:08,840 INFO [Thread-53] (EmployeeService.java:77) - oldMoney: 188
2018-04-25 16:24:08,840 INFO [Thread-95] (EmployeeService.java:77) - oldMoney: 188
2018-04-25 16:24:08,843 INFO [Thread-62] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,843 INFO [Thread-55] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,857 INFO [Thread-37] (EmployeeService.java:77) - oldMoney: 189
2018-04-25 16:24:08,872 INFO [Thread-94] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,872 INFO [Thread-53] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,887 INFO [Thread-15] (EmployeeService.java:77) - oldMoney: 190
2018-04-25 16:24:08,891 INFO [Thread-16] (EmployeeService.java:77) - oldMoney: 191
2018-04-25 16:24:08,902 INFO [Thread-37] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,909 INFO [Thread-14] (EmployeeService.java:77) - oldMoney: 192
2018-04-25 16:24:08,931 INFO [Thread-16] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,931 INFO [Thread-15] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,960 INFO [Thread-14] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:08,964 INFO [Thread-65] (EmployeeService.java:77) - oldMoney: 193
2018-04-25 16:24:08,965 INFO [Thread-42] (EmployeeService.java:77) - oldMoney: 194
2018-04-25 16:24:08,970 INFO [Thread-19] (EmployeeService.java:77) - oldMoney: 195
2018-04-25 16:24:08,989 INFO [Thread-65] (EmployeeService.java:65) - tryTimes: 3
2018-04-25 16:24:09,018 INFO [Thread-42] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:09,018 INFO [Thread-19] (EmployeeService.java:65) - tryTimes: 2
2018-04-25 16:24:09,025 INFO [Thread-40] (EmployeeService.java:77) - oldMoney: 196
2018-04-25 16:24:09,056 INFO [Thread-40] (EmployeeService.java:65) - tryTimes: 3
2018-04-25 16:24:09,318 INFO [Thread-43] (EmployeeService.java:77) - oldMoney: 197
2018-04-25 16:24:09,352 INFO [Thread-43] (EmployeeService.java:65) - tryTimes: 3
2018-04-25 16:24:09,433 INFO [Thread-7] (EmployeeService.java:77) - oldMoney: 198
2018-04-25 16:24:09,473 INFO [Thread-7] (EmployeeService.java:65) - tryTimes: 3
2018-04-25 16:24:09,578 INFO [Thread-95] (EmployeeService.java:77) - oldMoney: 199
2018-04-25 16:24:09,627 INFO [Thread-95] (EmployeeService.java:65) - tryTimes: 3
可以看到,还是有一些线程会拿到相同的值,但是由于版本控制使得最终只有一根线程能够更新成功,其它更新失败的线程会继续尝试,最终能更新成功。
第三部分 总结&对比
悲观锁 | 乐观锁 | |
概念 | 查询时直接锁住记录使得其它事务不能查询,更不能更新 | 提交更新时检查版本或者时间戳是否符合 |
语法 | select ... for update | 使用 version 或者 timestamp 进行比较 |
实现者 | 数据库本身 | 开发者 |
适用场景 | 并发量大 | 并发量小 |
类比Java | Synchronized关键字 | CAS 算法 |
Mysql锁机制--乐观锁 & 悲观锁的更多相关文章
- 乐观锁(optimistic locking)与悲观锁(pessimistic locking)
首先,乐观锁(optimistic locking)与悲观锁(pessimistic locking)基本是针对数据处理来说,也就是跟数据库有关的术语,目的是为了解决并发处理时所遇到的相关性能问题,以 ...
- 乐观、悲观锁、redis分布式锁
悲观锁总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给 ...
- Java CAS同步机制 原理详解(为什么并发环境下的COUNT自增操作不安全): Atomic原子类底层用的不是传统意义的锁机制,而是无锁化的CAS机制,通过CAS机制保证多线程修改一个数值的安全性。
精彩理解: https://www.jianshu.com/p/21be831e851e ; https://blog.csdn.net/heyutao007/article/details/19 ...
- MySQl中隔离级别和悲观锁乐观锁
1.MySql的事物支持 MySQL的事务支持不是绑定在MySQL服务器本身,而是与存储引擎相关: MyISAM:不支持事务,用于只读程序提高性能 InnoDB:支持ACID事务.行级锁.并发 Ber ...
- Hibernate学习---第十二节:Hibernate之锁机制&乐观锁实现
1.悲观锁 它指的是对数据被外界修改保持保守态度,因些,在整个数据处理过程中,将数据牌锁定状态.悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层的锁机制才能保证数据访问的排他性,否则,即使在本 ...
- MySQL- 锁机制及MyISAM表锁
锁是计算机协调多个进程或线程并发访问某一资源的机制.在数据库中,除传统的计算资源(如CPU.RAM.I/O等)的争用以外,数据也是一种供许 多用户 共享的资源.如何保证数据并发访问的一致性.有效性是所 ...
- JAVA锁机制-可重入锁,可中断锁,公平锁,读写锁,自旋锁,
如果需要查看具体的synchronized和lock的实现原理,请参考:解决多线程安全问题-无非两个方法synchronized和lock 具体原理(百度) 在并发编程中,经常遇到多个线程访问同一个 ...
- Java 线程锁机制 -Synchronized Lock 互斥锁 读写锁
(1)synchronized 是互斥锁: (2)ReentrantLock 顾名思义 :可重入锁 (3)ReadWriteLock :读写锁 读写锁特点: a)多个读者可以同时进行读b)写者必须互斥 ...
- 数据库并发事务控制四:postgresql数据库的锁机制二:表锁 <转>
在博文<数据库并发事务控制四:postgresql数据库的锁机制 > http://blog.csdn.net/beiigang/article/details/43302947 中后面提 ...
随机推荐
- python 模块部分补充知识
一.hashlib hashlib 模块主要用于加密相关的操作,代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法. 实例 ...
- 释义Oracle 11r2中并行执行相关参数
因最近对现场某些服务器进行诊断和调整,用到了这类参数,因此对这类参数做了详尽的查阅和研究,现将该类参数释义如下,以方便同行和自己参考,禁止转载: 1.PARALLEL_ADAPTIVE_MULTI_U ...
- MHA 安装与简单使用
MHA 在过去几年一直用的比较火,特别是在在传统复制的那个年代.至从有了GTID好像我们也可以把MHA给忘记了,但是很多企业现在还是在用的比较多.每个公司的MHA玩法也不太一样,但是本质都是差不多了. ...
- 新概念英语(1-47)A cup of coffee
新概念英语(1-47)A cup of coffee How does Ann like her coffee? A:Do you like coffee, Ann? B:Yes, I do. A:D ...
- mysql的账户管理
mysql中账户管理:1 查看所有用户: 所有用户及权限信息都存储在mysql数据库中的user表中 查看user表的结构 desc user\G; 主要字段: host: 表示允许访问的主机 use ...
- 用js来实现那些数据结构(数组篇02)
上一篇文章简单的介绍了一下js的类型,以及数组的增删方法.这一篇文章,我们一起来看看数组还有哪些用法,以及在实际工作中我们可以用这些方法来做些什么.由于其中有部分内容并不常用,所以我尽量缩小篇幅.在这 ...
- mybatis配置多数据源(利用spring的AbstractRoutingDataSource)
主要是利用了spring的AbstractRoutingDataSource. 直接上配置了: spring-mybatis.xml <bean name="dataSource&qu ...
- 文本处理三剑客之sed
sed 1.简介 sed是一种流编辑器,它一次处理一行内容.处理时,把当前处理的行存储在临时缓冲区中,称为"模式空间"(patternspace),接着用sed命令处理缓冲区中的内 ...
- SpringMVC(二):RequestMapping修饰类、指定请求方式、请求参数或请求头、支持Ant路径
@RequestMapping用来映射请求:RequestMapping可以修饰方法外,还可以修饰类 1)SpringMVC使用@RequestMapping注解为控制指定可以处理哪些URL请求: 2 ...
- Spring Cloud学习笔记-007
声明式服务调用:Spring Cloud Feign Feign基于Netflix Feign实现,整合了Spring Cloud Ribbon和Spring Cloud Hystrix,除了提供这两 ...