===============
從 這篇 文章中,我們知道 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 中的業務邏輯:
1 @Transactional(rollbackFor = RuntimeException.class) 2 public void increaseMoneyWithPessimisticLock(Integer id) { 3 Employee employee = employeeMapper.findByIdWithPessimisticLock(id); 4 final Integer oldMoney = employee.getMoney(); 5 LOGGER.info("oldMoney: {}", oldMoney); 6 employee.setMoney(oldMoney + 1); 7 employeeMapper.updateEmployee(employee); 8 }
提示:第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 查看日志

1 2018-04-25 15:12:14,335 INFO [Thread-5] (EmployeeService.java:36) - oldMoney: 0 2 2018-04-25 15:12:14,343 INFO [Thread-25] (EmployeeService.java:36) - oldMoney: 1 3 2018-04-25 15:12:14,345 INFO [Thread-27] (EmployeeService.java:36) - oldMoney: 2 4 2018-04-25 15:12:14,347 INFO [Thread-23] (EmployeeService.java:36) - oldMoney: 3 5 2018-04-25 15:12:14,349 INFO [Thread-13] (EmployeeService.java:36) - oldMoney: 4 6 2018-04-25 15:12:14,350 INFO [Thread-38] (EmployeeService.java:36) - oldMoney: 5 7 2018-04-25 15:12:14,351 INFO [Thread-24] (EmployeeService.java:36) - oldMoney: 6 8 2018-04-25 15:12:14,353 INFO [Thread-4] (EmployeeService.java:36) - oldMoney: 7 9 2018-04-25 15:12:14,355 INFO [Thread-26] (EmployeeService.java:36) - oldMoney: 8 10 2018-04-25 15:12:14,357 INFO [Thread-8] (EmployeeService.java:36) - oldMoney: 9 11 2018-04-25 15:12:14,360 INFO [Thread-3] (EmployeeService.java:36) - oldMoney: 10 12 2018-04-25 15:12:14,361 INFO [Thread-81] (EmployeeService.java:36) - oldMoney: 11 13 2018-04-25 15:12:14,363 INFO [Thread-20] (EmployeeService.java:36) - oldMoney: 12 14 2018-04-25 15:12:14,365 INFO [Thread-40] (EmployeeService.java:36) - oldMoney: 13 15 2018-04-25 15:12:14,366 INFO [Thread-29] (EmployeeService.java:36) - oldMoney: 14 16 2018-04-25 15:12:14,453 INFO [Thread-14] (EmployeeService.java:36) - oldMoney: 15 17 2018-04-25 15:12:14,475 INFO [Thread-7] (EmployeeService.java:36) - oldMoney: 16 18 2018-04-25 15:12:14,485 INFO [Thread-11] (EmployeeService.java:36) - oldMoney: 17 19 2018-04-25 15:12:14,488 INFO [Thread-48] (EmployeeService.java:36) - oldMoney: 18 20 2018-04-25 15:12:14,491 INFO [Thread-47] (EmployeeService.java:36) - oldMoney: 19 21 2018-04-25 15:12:14,494 INFO [Thread-12] (EmployeeService.java:36) - oldMoney: 20 22 2018-04-25 15:12:14,497 INFO [Thread-72] (EmployeeService.java:36) - oldMoney: 21 23 2018-04-25 15:12:14,500 INFO [Thread-46] (EmployeeService.java:36) - oldMoney: 22 24 2018-04-25 15:12:14,501 INFO [Thread-44] (EmployeeService.java:36) - oldMoney: 23 25 2018-04-25 15:12:14,503 INFO [Thread-45] (EmployeeService.java:36) - oldMoney: 24 26 2018-04-25 15:12:14,504 INFO [Thread-41] (EmployeeService.java:36) - oldMoney: 25 27 2018-04-25 15:12:14,505 INFO [Thread-9] (EmployeeService.java:36) - oldMoney: 26 28 2018-04-25 15:12:14,507 INFO [Thread-19] (EmployeeService.java:36) - oldMoney: 27 29 2018-04-25 15:12:14,508 INFO [Thread-55] (EmployeeService.java:36) - oldMoney: 28 30 2018-04-25 15:12:14,509 INFO [Thread-36] (EmployeeService.java:36) - oldMoney: 29 31 2018-04-25 15:12:14,518 INFO [Thread-43] (EmployeeService.java:36) - oldMoney: 30 32 2018-04-25 15:12:14,547 INFO [Thread-53] (EmployeeService.java:36) - oldMoney: 31 33 2018-04-25 15:12:14,556 INFO [Thread-52] (EmployeeService.java:36) - oldMoney: 32 34 2018-04-25 15:12:14,558 INFO [Thread-51] (EmployeeService.java:36) - oldMoney: 33 35 2018-04-25 15:12:14,560 INFO [Thread-50] (EmployeeService.java:36) - oldMoney: 34 36 2018-04-25 15:12:14,562 INFO [Thread-32] (EmployeeService.java:36) - oldMoney: 35 37 2018-04-25 15:12:14,563 INFO [Thread-85] (EmployeeService.java:36) - oldMoney: 36 38 2018-04-25 15:12:14,565 INFO [Thread-84] (EmployeeService.java:36) - oldMoney: 37 39 2018-04-25 15:12:14,567 INFO [Thread-33] (EmployeeService.java:36) - oldMoney: 38 40 2018-04-25 15:12:14,568 INFO [Thread-82] (EmployeeService.java:36) - oldMoney: 39 41 2018-04-25 15:12:14,570 INFO [Thread-34] (EmployeeService.java:36) - oldMoney: 40 42 2018-04-25 15:12:14,571 INFO [Thread-35] (EmployeeService.java:36) - oldMoney: 41 43 2018-04-25 15:12:14,573 INFO [Thread-83] (EmployeeService.java:36) - oldMoney: 42 44 2018-04-25 15:12:14,574 INFO [Thread-42] (EmployeeService.java:36) - oldMoney: 43 45 2018-04-25 15:12:14,575 INFO [Thread-22] (EmployeeService.java:36) - oldMoney: 44 46 2018-04-25 15:12:14,585 INFO [Thread-30] (EmployeeService.java:36) - oldMoney: 45 47 2018-04-25 15:12:14,586 INFO [Thread-28] (EmployeeService.java:36) - oldMoney: 46 48 2018-04-25 15:12:14,613 INFO [Thread-16] (EmployeeService.java:36) - oldMoney: 47 49 2018-04-25 15:12:14,615 INFO [Thread-17] (EmployeeService.java:36) - oldMoney: 48 50 2018-04-25 15:12:14,616 INFO [Thread-21] (EmployeeService.java:36) - oldMoney: 49 51 2018-04-25 15:12:14,618 INFO [Thread-18] (EmployeeService.java:36) - oldMoney: 50 52 2018-04-25 15:12:14,619 INFO [Thread-37] (EmployeeService.java:36) - oldMoney: 51 53 2018-04-25 15:12:14,621 INFO [Thread-39] (EmployeeService.java:36) - oldMoney: 52 54 2018-04-25 15:12:14,623 INFO [Thread-2] (EmployeeService.java:36) - oldMoney: 53 55 2018-04-25 15:12:14,624 INFO [Thread-1] (EmployeeService.java:36) - oldMoney: 54 56 2018-04-25 15:12:14,626 INFO [Thread-10] (EmployeeService.java:36) - oldMoney: 55 57 2018-04-25 15:12:14,627 INFO [Thread-15] (EmployeeService.java:36) - oldMoney: 56 58 2018-04-25 15:12:14,628 INFO [Thread-56] (EmployeeService.java:36) - oldMoney: 57 59 2018-04-25 15:12:14,630 INFO [Thread-54] (EmployeeService.java:36) - oldMoney: 58 60 2018-04-25 15:12:14,632 INFO [Thread-31] (EmployeeService.java:36) - oldMoney: 59 61 2018-04-25 15:12:14,642 INFO [Thread-57] (EmployeeService.java:36) - oldMoney: 60 62 2018-04-25 15:12:14,645 INFO [Thread-6] (EmployeeService.java:36) - oldMoney: 61 63 2018-04-25 15:12:14,672 INFO [Thread-62] (EmployeeService.java:36) - oldMoney: 62 64 2018-04-25 15:12:14,677 INFO [Thread-59] (EmployeeService.java:36) - oldMoney: 63 65 2018-04-25 15:12:14,679 INFO [Thread-61] (EmployeeService.java:36) - oldMoney: 64 66 2018-04-25 15:12:14,680 INFO [Thread-58] (EmployeeService.java:36) - oldMoney: 65 67 2018-04-25 15:12:14,681 INFO [Thread-80] (EmployeeService.java:36) - oldMoney: 66 68 2018-04-25 15:12:14,682 INFO [Thread-76] (EmployeeService.java:36) - oldMoney: 67 69 2018-04-25 15:12:14,684 INFO [Thread-78] (EmployeeService.java:36) - oldMoney: 68 70 2018-04-25 15:12:14,685 INFO [Thread-100] (EmployeeService.java:36) - oldMoney: 69 71 2018-04-25 15:12:14,686 INFO [Thread-99] (EmployeeService.java:36) - oldMoney: 70 72 2018-04-25 15:12:14,688 INFO [Thread-79] (EmployeeService.java:36) - oldMoney: 71 73 2018-04-25 15:12:14,689 INFO [Thread-94] (EmployeeService.java:36) - oldMoney: 72 74 2018-04-25 15:12:14,690 INFO [Thread-60] (EmployeeService.java:36) - oldMoney: 73 75 2018-04-25 15:12:14,691 INFO [Thread-77] (EmployeeService.java:36) - oldMoney: 74 76 2018-04-25 15:12:14,709 INFO [Thread-95] (EmployeeService.java:36) - oldMoney: 75 77 2018-04-25 15:12:14,711 INFO [Thread-96] (EmployeeService.java:36) - oldMoney: 76 78 2018-04-25 15:12:14,712 INFO [Thread-98] (EmployeeService.java:36) - oldMoney: 77 79 2018-04-25 15:12:14,738 INFO [Thread-75] (EmployeeService.java:36) - oldMoney: 78 80 2018-04-25 15:12:14,740 INFO [Thread-74] (EmployeeService.java:36) - oldMoney: 79 81 2018-04-25 15:12:14,741 INFO [Thread-73] (EmployeeService.java:36) - oldMoney: 80 82 2018-04-25 15:12:14,742 INFO [Thread-71] (EmployeeService.java:36) - oldMoney: 81 83 2018-04-25 15:12:14,743 INFO [Thread-69] (EmployeeService.java:36) - oldMoney: 82 84 2018-04-25 15:12:14,745 INFO [Thread-70] (EmployeeService.java:36) - oldMoney: 83 85 2018-04-25 15:12:14,746 INFO [Thread-68] (EmployeeService.java:36) - oldMoney: 84 86 2018-04-25 15:12:14,748 INFO [Thread-66] (EmployeeService.java:36) - oldMoney: 85 87 2018-04-25 15:12:14,749 INFO [Thread-67] (EmployeeService.java:36) - oldMoney: 86 88 2018-04-25 15:12:14,751 INFO [Thread-64] (EmployeeService.java:36) - oldMoney: 87 89 2018-04-25 15:12:14,754 INFO [Thread-65] (EmployeeService.java:36) - oldMoney: 88 90 2018-04-25 15:12:14,755 INFO [Thread-63] (EmployeeService.java:36) - oldMoney: 89 91 2018-04-25 15:12:14,767 INFO [Thread-97] (EmployeeService.java:36) - oldMoney: 90 92 2018-04-25 15:12:14,769 INFO [Thread-93] (EmployeeService.java:36) - oldMoney: 91 93 2018-04-25 15:12:14,770 INFO [Thread-49] (EmployeeService.java:36) - oldMoney: 92 94 2018-04-25 15:12:14,796 INFO [Thread-92] (EmployeeService.java:36) - oldMoney: 93 95 2018-04-25 15:12:14,801 INFO [Thread-91] (EmployeeService.java:36) - oldMoney: 94 96 2018-04-25 15:12:14,803 INFO [Thread-89] (EmployeeService.java:36) - oldMoney: 95 97 2018-04-25 15:12:14,803 INFO [Thread-90] (EmployeeService.java:36) - oldMoney: 96 98 2018-04-25 15:12:14,804 INFO [Thread-88] (EmployeeService.java:36) - oldMoney: 97 99 2018-04-25 15:12:14,806 INFO [Thread-87] (EmployeeService.java:36) - oldMoney: 98 100 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 中的業務邏輯:
1 /** 2 * 失敗嘗試 3 * @param id 4 */ 5 public void increaseMoneyWithOptimisticLock(Integer id) { 6 int tryTimes = 0; 7 while (true) { 8 tryTimes++; 9 if (internalIncreaseMoneyWithOptimisticLock(id) != 0) { 10 // 說明更新成功,直接退出 11 break; 12 } 13 if (tryTimes == 200) { 14 // 達到最大重試次數,退出 15 break; 16 } 17 try { 18 // 休息一段時間后再重試 19 TimeUnit.MILLISECONDS.sleep(new Random().nextInt(1000)); 20 } catch (InterruptedException e) { 21 e.printStackTrace(); 22 Thread.currentThread().interrupt(); 23 } 24 } 25 LOGGER.info("tryTimes: {}", tryTimes); 26 } 27 28 /** 29 * 查找Employee對象,並進行更新 30 * @param id 31 * @return 32 */ 33 @Transactional(rollbackFor = RuntimeException.class) 34 public Integer internalIncreaseMoneyWithOptimisticLock(Integer id) { 35 Employee employee = employeeMapper.findById(id); 36 final Integer oldMoney = employee.getMoney(); 37 LOGGER.info("oldMoney: {}", oldMoney); 38 employee.setMoney(oldMoney + 1); 39 return employeeMapper.updateEmployeeWithOptimisticLock(employee); 40 }
提示:
- 樂觀鎖,其實是開發者自己實現的邏輯
- 更新失敗后,休息一段時間后再進行重試
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 查看日志

1 2018-04-25 16:24:07,851 INFO [Thread-36] (EmployeeService.java:77) - oldMoney: 100 2 2018-04-25 16:24:07,853 INFO [Thread-54] (EmployeeService.java:77) - oldMoney: 100 3 2018-04-25 16:24:07,856 INFO [Thread-55] (EmployeeService.java:77) - oldMoney: 100 4 2018-04-25 16:24:07,856 INFO [Thread-45] (EmployeeService.java:77) - oldMoney: 100 5 2018-04-25 16:24:07,858 INFO [Thread-56] (EmployeeService.java:77) - oldMoney: 100 6 2018-04-25 16:24:07,858 INFO [Thread-53] (EmployeeService.java:77) - oldMoney: 100 7 2018-04-25 16:24:07,858 INFO [Thread-33] (EmployeeService.java:77) - oldMoney: 100 8 2018-04-25 16:24:07,859 INFO [Thread-57] (EmployeeService.java:77) - oldMoney: 100 9 2018-04-25 16:24:07,859 INFO [Thread-31] (EmployeeService.java:77) - oldMoney: 100 10 2018-04-25 16:24:07,863 INFO [Thread-30] (EmployeeService.java:77) - oldMoney: 101 11 2018-04-25 16:24:07,868 INFO [Thread-29] (EmployeeService.java:77) - oldMoney: 101 12 2018-04-25 16:24:07,880 INFO [Thread-75] (EmployeeService.java:77) - oldMoney: 101 13 2018-04-25 16:24:07,881 INFO [Thread-76] (EmployeeService.java:77) - oldMoney: 102 14 2018-04-25 16:24:07,882 INFO [Thread-78] (EmployeeService.java:77) - oldMoney: 102 15 2018-04-25 16:24:07,883 INFO [Thread-77] (EmployeeService.java:77) - oldMoney: 102 16 2018-04-25 16:24:07,885 INFO [Thread-79] (EmployeeService.java:77) - oldMoney: 103 17 2018-04-25 16:24:07,887 INFO [Thread-80] (EmployeeService.java:77) - oldMoney: 103 18 2018-04-25 16:24:07,888 INFO [Thread-28] (EmployeeService.java:77) - oldMoney: 104 19 2018-04-25 16:24:07,890 INFO [Thread-27] (EmployeeService.java:77) - oldMoney: 104 20 2018-04-25 16:24:07,892 INFO [Thread-26] (EmployeeService.java:77) - oldMoney: 105 21 2018-04-25 16:24:07,894 INFO [Thread-25] (EmployeeService.java:77) - oldMoney: 105 22 2018-04-25 16:24:07,895 INFO [Thread-24] (EmployeeService.java:77) - oldMoney: 106 23 2018-04-25 16:24:07,897 INFO [Thread-83] (EmployeeService.java:77) - oldMoney: 106 24 2018-04-25 16:24:07,898 INFO [Thread-82] (EmployeeService.java:77) - oldMoney: 106 25 2018-04-25 16:24:07,900 INFO [Thread-84] (EmployeeService.java:77) - oldMoney: 107 26 2018-04-25 16:24:07,904 INFO [Thread-21] (EmployeeService.java:77) - oldMoney: 108 27 2018-04-25 16:24:07,906 INFO [Thread-20] (EmployeeService.java:77) - oldMoney: 109 28 2018-04-25 16:24:07,907 INFO [Thread-6] (EmployeeService.java:77) - oldMoney: 109 29 2018-04-25 16:24:07,908 INFO [Thread-9] (EmployeeService.java:77) - oldMoney: 110 30 2018-04-25 16:24:07,909 INFO [Thread-85] (EmployeeService.java:77) - oldMoney: 110 31 2018-04-25 16:24:07,909 INFO [Thread-86] (EmployeeService.java:77) - oldMoney: 111 32 2018-04-25 16:24:07,911 INFO [Thread-91] (EmployeeService.java:77) - oldMoney: 111 33 2018-04-25 16:24:07,912 INFO [Thread-81] (EmployeeService.java:77) - oldMoney: 112 34 2018-04-25 16:24:07,913 INFO [Thread-90] (EmployeeService.java:77) - oldMoney: 112 35 2018-04-25 16:24:07,915 INFO [Thread-96] (EmployeeService.java:77) - oldMoney: 112 36 2018-04-25 16:24:07,924 INFO [Thread-97] (EmployeeService.java:77) - oldMoney: 113 37 2018-04-25 16:24:07,926 INFO [Thread-36] (EmployeeService.java:65) - tryTimes: 1 38 2018-04-25 16:24:07,928 INFO [Thread-18] (EmployeeService.java:77) - oldMoney: 113 39 2018-04-25 16:24:07,929 INFO [Thread-4] (EmployeeService.java:77) - oldMoney: 113 40 2018-04-25 16:24:07,932 INFO [Thread-94] (EmployeeService.java:77) - oldMoney: 114 41 2018-04-25 16:24:07,934 INFO [Thread-12] (EmployeeService.java:77) - oldMoney: 114 42 2018-04-25 16:24:07,935 INFO [Thread-93] (EmployeeService.java:77) - oldMoney: 114 43 2018-04-25 16:24:07,939 INFO [Thread-92] (EmployeeService.java:77) - oldMoney: 115 44 2018-04-25 16:24:07,940 INFO [Thread-69] (EmployeeService.java:77) - oldMoney: 115 45 2018-04-25 16:24:07,960 INFO [Thread-86] (EmployeeService.java:65) - tryTimes: 1 46 2018-04-25 16:24:07,961 INFO [Thread-9] (EmployeeService.java:65) - tryTimes: 1 47 2018-04-25 16:24:07,960 INFO [Thread-75] (EmployeeService.java:65) - tryTimes: 1 48 2018-04-25 16:24:07,962 INFO [Thread-33] (EmployeeService.java:77) - oldMoney: 116 49 2018-04-25 16:24:07,963 INFO [Thread-87] (EmployeeService.java:77) - oldMoney: 116 50 2018-04-25 16:24:07,963 INFO [Thread-6] (EmployeeService.java:77) - oldMoney: 116 51 2018-04-25 16:24:07,964 INFO [Thread-20] (EmployeeService.java:65) - tryTimes: 1 52 2018-04-25 16:24:07,964 INFO [Thread-21] (EmployeeService.java:65) - tryTimes: 1 53 2018-04-25 16:24:07,964 INFO [Thread-90] (EmployeeService.java:65) - tryTimes: 1 54 2018-04-25 16:24:07,965 INFO [Thread-26] (EmployeeService.java:65) - tryTimes: 1 55 2018-04-25 16:24:07,965 INFO [Thread-28] (EmployeeService.java:65) - tryTimes: 1 56 2018-04-25 16:24:07,965 INFO [Thread-83] (EmployeeService.java:65) - tryTimes: 1 57 2018-04-25 16:24:07,966 INFO [Thread-76] (EmployeeService.java:65) - tryTimes: 1 58 2018-04-25 16:24:07,966 INFO [Thread-79] (EmployeeService.java:65) - tryTimes: 1 59 2018-04-25 16:24:07,967 INFO [Thread-84] (EmployeeService.java:65) - tryTimes: 1 60 2018-04-25 16:24:07,974 INFO [Thread-16] (EmployeeService.java:77) - oldMoney: 116 61 2018-04-25 16:24:07,974 INFO [Thread-17] (EmployeeService.java:77) - oldMoney: 116 62 2018-04-25 16:24:07,974 INFO [Thread-89] (EmployeeService.java:77) - oldMoney: 116 63 2018-04-25 16:24:07,975 INFO [Thread-13] (EmployeeService.java:77) - oldMoney: 116 64 2018-04-25 16:24:07,976 INFO [Thread-7] (EmployeeService.java:77) - oldMoney: 116 65 2018-04-25 16:24:07,976 INFO [Thread-100] (EmployeeService.java:77) - oldMoney: 116 66 2018-04-25 16:24:07,976 INFO [Thread-95] (EmployeeService.java:77) - oldMoney: 116 67 2018-04-25 16:24:07,978 INFO [Thread-88] (EmployeeService.java:77) - oldMoney: 116 68 2018-04-25 16:24:07,978 INFO [Thread-8] (EmployeeService.java:77) - oldMoney: 117 69 2018-04-25 16:24:07,979 INFO [Thread-11] (EmployeeService.java:77) - oldMoney: 117 70 2018-04-25 16:24:07,980 INFO [Thread-5] (EmployeeService.java:77) - oldMoney: 118 71 2018-04-25 16:24:07,980 INFO [Thread-19] (EmployeeService.java:77) - oldMoney: 118 72 2018-04-25 16:24:07,980 INFO [Thread-22] (EmployeeService.java:77) - oldMoney: 118 73 2018-04-25 16:24:07,981 INFO [Thread-2] (EmployeeService.java:77) - oldMoney: 119 74 2018-04-25 16:24:07,981 INFO [Thread-23] (EmployeeService.java:77) - oldMoney: 119 75 2018-04-25 16:24:07,982 INFO [Thread-35] (EmployeeService.java:77) - oldMoney: 119 76 2018-04-25 16:24:07,982 INFO [Thread-32] (EmployeeService.java:77) - oldMoney: 119 77 2018-04-25 16:24:07,983 INFO [Thread-34] (EmployeeService.java:77) - oldMoney: 120 78 2018-04-25 16:24:07,983 INFO [Thread-37] (EmployeeService.java:77) - oldMoney: 120 79 2018-04-25 16:24:07,984 INFO [Thread-38] (EmployeeService.java:77) - oldMoney: 120 80 2018-04-25 16:24:07,985 INFO [Thread-39] (EmployeeService.java:77) - oldMoney: 121 81 2018-04-25 16:24:07,985 INFO [Thread-40] (EmployeeService.java:77) - oldMoney: 121 82 2018-04-25 16:24:07,986 INFO [Thread-41] (EmployeeService.java:77) - oldMoney: 121 83 2018-04-25 16:24:07,986 INFO [Thread-43] (EmployeeService.java:77) - oldMoney: 121 84 2018-04-25 16:24:07,987 INFO [Thread-44] (EmployeeService.java:77) - oldMoney: 122 85 2018-04-25 16:24:07,988 INFO [Thread-48] (EmployeeService.java:77) - oldMoney: 122 86 2018-04-25 16:24:07,988 INFO [Thread-49] (EmployeeService.java:77) - oldMoney: 122 87 2018-04-25 16:24:07,989 INFO [Thread-50] (EmployeeService.java:77) - oldMoney: 122 88 2018-04-25 16:24:07,986 INFO [Thread-42] (EmployeeService.java:77) - oldMoney: 121 89 2018-04-25 16:24:07,990 INFO [Thread-52] (EmployeeService.java:77) - oldMoney: 123 90 2018-04-25 16:24:07,989 INFO [Thread-51] (EmployeeService.java:77) - oldMoney: 122 91 2018-04-25 16:24:07,988 INFO [Thread-47] (EmployeeService.java:77) - oldMoney: 122 92 2018-04-25 16:24:07,987 INFO [Thread-46] (EmployeeService.java:77) - oldMoney: 122 93 2018-04-25 16:24:07,991 INFO [Thread-60] (EmployeeService.java:77) - oldMoney: 123 94 2018-04-25 16:24:07,990 INFO [Thread-58] (EmployeeService.java:77) - oldMoney: 123 95 2018-04-25 16:24:07,992 INFO [Thread-64] (EmployeeService.java:77) - oldMoney: 124 96 2018-04-25 16:24:07,992 INFO [Thread-65] (EmployeeService.java:77) - oldMoney: 124 97 2018-04-25 16:24:07,992 INFO [Thread-61] (EmployeeService.java:77) - oldMoney: 124 98 2018-04-25 16:24:07,993 INFO [Thread-63] (EmployeeService.java:77) - oldMoney: 125 99 2018-04-25 16:24:07,995 INFO [Thread-68] (EmployeeService.java:77) - oldMoney: 125 100 2018-04-25 16:24:07,995 INFO [Thread-67] (EmployeeService.java:77) - oldMoney: 125 101 2018-04-25 16:24:07,995 INFO [Thread-15] (EmployeeService.java:77) - oldMoney: 125 102 2018-04-25 16:24:07,996 INFO [Thread-66] (EmployeeService.java:77) - oldMoney: 125 103 2018-04-25 16:24:07,997 INFO [Thread-99] (EmployeeService.java:77) - oldMoney: 126 104 2018-04-25 16:24:07,998 INFO [Thread-98] (EmployeeService.java:77) - oldMoney: 126 105 2018-04-25 16:24:07,998 INFO [Thread-74] (EmployeeService.java:77) - oldMoney: 126 106 2018-04-25 16:24:08,002 INFO [Thread-92] (EmployeeService.java:65) - tryTimes: 1 107 2018-04-25 16:24:08,002 INFO [Thread-73] (EmployeeService.java:77) - oldMoney: 127 108 2018-04-25 16:24:08,002 INFO [Thread-18] (EmployeeService.java:65) - tryTimes: 1 109 2018-04-25 16:24:08,004 INFO [Thread-62] (EmployeeService.java:77) - oldMoney: 127 110 2018-04-25 16:24:08,004 INFO [Thread-27] (EmployeeService.java:77) - oldMoney: 127 111 2018-04-25 16:24:08,005 INFO [Thread-46] (EmployeeService.java:77) - oldMoney: 128 112 2018-04-25 16:24:08,006 INFO [Thread-59] (EmployeeService.java:77) - oldMoney: 128 113 2018-04-25 16:24:08,006 INFO [Thread-71] (EmployeeService.java:77) - oldMoney: 128 114 2018-04-25 16:24:08,006 INFO [Thread-3] (EmployeeService.java:77) - oldMoney: 128 115 2018-04-25 16:24:08,007 INFO [Thread-56] (EmployeeService.java:77) - oldMoney: 128 116 2018-04-25 16:24:08,008 INFO [Thread-72] (EmployeeService.java:77) - oldMoney: 128 117 2018-04-25 16:24:08,008 INFO [Thread-93] (EmployeeService.java:65) - tryTimes: 1 118 2018-04-25 16:24:08,010 INFO [Thread-70] (EmployeeService.java:77) - oldMoney: 129 119 2018-04-25 16:24:08,010 INFO [Thread-10] (EmployeeService.java:77) - oldMoney: 129 120 2018-04-25 16:24:08,010 INFO [Thread-17] (EmployeeService.java:77) - oldMoney: 129 121 2018-04-25 16:24:08,011 INFO [Thread-14] (EmployeeService.java:77) - oldMoney: 129 122 2018-04-25 16:24:08,012 INFO [Thread-1] (EmployeeService.java:77) - oldMoney: 130 123 2018-04-25 16:24:08,032 INFO [Thread-5] (EmployeeService.java:65) - tryTimes: 1 124 2018-04-25 16:24:08,032 INFO [Thread-49] (EmployeeService.java:65) - tryTimes: 1 125 2018-04-25 16:24:08,032 INFO [Thread-87] (EmployeeService.java:65) - tryTimes: 1 126 2018-04-25 16:24:08,032 INFO [Thread-64] (EmployeeService.java:65) - tryTimes: 1 127 2018-04-25 16:24:08,032 INFO [Thread-8] (EmployeeService.java:65) - tryTimes: 1 128 2018-04-25 16:24:08,033 INFO [Thread-41] (EmployeeService.java:65) - tryTimes: 1 129 2018-04-25 16:24:08,033 INFO [Thread-52] (EmployeeService.java:65) - tryTimes: 1 130 2018-04-25 16:24:08,034 INFO [Thread-2] (EmployeeService.java:65) - tryTimes: 1 131 2018-04-25 16:24:08,034 INFO [Thread-72] (EmployeeService.java:77) - oldMoney: 131 132 2018-04-25 16:24:08,035 INFO [Thread-99] (EmployeeService.java:65) - tryTimes: 1 133 2018-04-25 16:24:08,035 INFO [Thread-34] (EmployeeService.java:65) - tryTimes: 1 134 2018-04-25 16:24:08,035 INFO [Thread-68] (EmployeeService.java:65) - tryTimes: 1 135 2018-04-25 16:24:08,037 INFO [Thread-30] (EmployeeService.java:77) - oldMoney: 131 136 2018-04-25 16:24:08,049 INFO [Thread-30] (EmployeeService.java:77) - oldMoney: 132 137 2018-04-25 16:24:08,068 INFO [Thread-3] (EmployeeService.java:65) - tryTimes: 1 138 2018-04-25 16:24:08,068 INFO [Thread-10] (EmployeeService.java:65) - tryTimes: 1 139 2018-04-25 16:24:08,068 INFO [Thread-73] (EmployeeService.java:65) - tryTimes: 1 140 2018-04-25 16:24:08,068 INFO [Thread-1] (EmployeeService.java:65) - tryTimes: 1 141 2018-04-25 16:24:08,070 INFO [Thread-24] (EmployeeService.java:77) - oldMoney: 133 142 2018-04-25 16:24:08,082 INFO [Thread-69] (EmployeeService.java:77) - oldMoney: 134 143 2018-04-25 16:24:08,087 INFO [Thread-60] (EmployeeService.java:77) - oldMoney: 135 144 2018-04-25 16:24:08,117 INFO [Thread-38] (EmployeeService.java:77) - oldMoney: 136 145 2018-04-25 16:24:08,125 INFO [Thread-46] (EmployeeService.java:77) - oldMoney: 137 146 2018-04-25 16:24:08,131 INFO [Thread-30] (EmployeeService.java:65) - tryTimes: 3 147 2018-04-25 16:24:08,132 INFO [Thread-72] (EmployeeService.java:65) - tryTimes: 2 148 2018-04-25 16:24:08,149 INFO [Thread-11] (EmployeeService.java:77) - oldMoney: 138 149 2018-04-25 16:24:08,170 INFO [Thread-98] (EmployeeService.java:77) - oldMoney: 139 150 2018-04-25 16:24:08,180 INFO [Thread-60] (EmployeeService.java:65) - tryTimes: 2 151 2018-04-25 16:24:08,181 INFO [Thread-46] (EmployeeService.java:65) - tryTimes: 3 152 2018-04-25 16:24:08,180 INFO [Thread-69] (EmployeeService.java:65) - tryTimes: 2 153 2018-04-25 16:24:08,180 INFO [Thread-38] (EmployeeService.java:65) - tryTimes: 2 154 2018-04-25 16:24:08,180 INFO [Thread-24] (EmployeeService.java:65) - tryTimes: 2 155 2018-04-25 16:24:08,188 INFO [Thread-71] (EmployeeService.java:77) - oldMoney: 140 156 2018-04-25 16:24:08,204 INFO [Thread-96] (EmployeeService.java:77) - oldMoney: 141 157 2018-04-25 16:24:08,210 INFO [Thread-11] (EmployeeService.java:65) - tryTimes: 2 158 2018-04-25 16:24:08,210 INFO [Thread-98] (EmployeeService.java:65) - tryTimes: 2 159 2018-04-25 16:24:08,230 INFO [Thread-91] (EmployeeService.java:77) - oldMoney: 142 160 2018-04-25 16:24:08,239 INFO [Thread-71] (EmployeeService.java:65) - tryTimes: 2 161 2018-04-25 16:24:08,239 INFO [Thread-96] (EmployeeService.java:65) - tryTimes: 2 162 2018-04-25 16:24:08,254 INFO [Thread-25] (EmployeeService.java:77) - oldMoney: 143 163 2018-04-25 16:24:08,254 INFO [Thread-58] (EmployeeService.java:77) - oldMoney: 143 164 2018-04-25 16:24:08,263 INFO [Thread-17] (EmployeeService.java:77) - oldMoney: 144 165 2018-04-25 16:24:08,268 INFO [Thread-91] (EmployeeService.java:65) - tryTimes: 2 166 2018-04-25 16:24:08,275 INFO [Thread-63] (EmployeeService.java:77) - oldMoney: 145 167 2018-04-25 16:24:08,275 INFO [Thread-89] (EmployeeService.java:77) - oldMoney: 145 168 2018-04-25 16:24:08,277 INFO [Thread-51] (EmployeeService.java:77) - oldMoney: 146 169 2018-04-25 16:24:08,279 INFO [Thread-56] (EmployeeService.java:77) - oldMoney: 147 170 2018-04-25 16:24:08,280 INFO [Thread-40] (EmployeeService.java:77) - oldMoney: 147 171 2018-04-25 16:24:08,280 INFO [Thread-65] (EmployeeService.java:77) - oldMoney: 147 172 2018-04-25 16:24:08,287 INFO [Thread-100] (EmployeeService.java:77) - oldMoney: 148 173 2018-04-25 16:24:08,298 INFO [Thread-25] (EmployeeService.java:65) - tryTimes: 2 174 2018-04-25 16:24:08,299 INFO [Thread-17] (EmployeeService.java:65) - tryTimes: 3 175 2018-04-25 16:24:08,310 INFO [Thread-47] (EmployeeService.java:77) - oldMoney: 149 176 2018-04-25 16:24:08,319 INFO [Thread-6] (EmployeeService.java:77) - oldMoney: 150 177 2018-04-25 16:24:08,327 INFO [Thread-100] (EmployeeService.java:65) - tryTimes: 2 178 2018-04-25 16:24:08,327 INFO [Thread-56] (EmployeeService.java:65) - tryTimes: 3 179 2018-04-25 16:24:08,327 INFO [Thread-63] (EmployeeService.java:65) - tryTimes: 2 180 2018-04-25 16:24:08,328 INFO [Thread-51] (EmployeeService.java:65) - tryTimes: 2 181 2018-04-25 16:24:08,364 INFO [Thread-6] (EmployeeService.java:65) - tryTimes: 3 182 2018-04-25 16:24:08,365 INFO [Thread-47] (EmployeeService.java:65) - tryTimes: 2 183 2018-04-25 16:24:08,388 INFO [Thread-33] (EmployeeService.java:77) - oldMoney: 151 184 2018-04-25 16:24:08,400 INFO [Thread-58] (EmployeeService.java:77) - oldMoney: 152 185 2018-04-25 16:24:08,404 INFO [Thread-35] (EmployeeService.java:77) - oldMoney: 153 186 2018-04-25 16:24:08,424 INFO [Thread-89] (EmployeeService.java:77) - oldMoney: 154 187 2018-04-25 16:24:08,427 INFO [Thread-33] (EmployeeService.java:65) - tryTimes: 3 188 2018-04-25 16:24:08,431 INFO [Thread-88] (EmployeeService.java:77) - oldMoney: 155 189 2018-04-25 16:24:08,453 INFO [Thread-12] (EmployeeService.java:77) - oldMoney: 156 190 2018-04-25 16:24:08,454 INFO [Thread-70] (EmployeeService.java:77) - oldMoney: 157 191 2018-04-25 16:24:08,457 INFO [Thread-89] (EmployeeService.java:65) - tryTimes: 3 192 2018-04-25 16:24:08,457 INFO [Thread-58] (EmployeeService.java:65) - tryTimes: 3 193 2018-04-25 16:24:08,458 INFO [Thread-35] (EmployeeService.java:65) - tryTimes: 2 194 2018-04-25 16:24:08,459 INFO [Thread-54] (EmployeeService.java:77) - oldMoney: 158 195 2018-04-25 16:24:08,461 INFO [Thread-67] (EmployeeService.java:77) - oldMoney: 159 196 2018-04-25 16:24:08,470 INFO [Thread-31] (EmployeeService.java:77) - oldMoney: 160 197 2018-04-25 16:24:08,485 INFO [Thread-12] (EmployeeService.java:65) - tryTimes: 2 198 2018-04-25 16:24:08,485 INFO [Thread-70] (EmployeeService.java:65) - tryTimes: 2 199 2018-04-25 16:24:08,486 INFO [Thread-88] (EmployeeService.java:65) - tryTimes: 2 200 2018-04-25 16:24:08,488 INFO [Thread-81] (EmployeeService.java:77) - oldMoney: 161 201 2018-04-25 16:24:08,497 INFO [Thread-23] (EmployeeService.java:77) - oldMoney: 162 202 2018-04-25 16:24:08,504 INFO [Thread-82] (EmployeeService.java:77) - oldMoney: 163 203 2018-04-25 16:24:08,507 INFO [Thread-50] (EmployeeService.java:77) - oldMoney: 164 204 2018-04-25 16:24:08,510 INFO [Thread-78] (EmployeeService.java:77) - oldMoney: 165 205 2018-04-25 16:24:08,514 INFO [Thread-67] (EmployeeService.java:65) - tryTimes: 2 206 2018-04-25 16:24:08,514 INFO [Thread-54] (EmployeeService.java:65) - tryTimes: 2 207 2018-04-25 16:24:08,516 INFO [Thread-97] (EmployeeService.java:77) - oldMoney: 166 208 2018-04-25 16:24:08,517 INFO [Thread-31] (EmployeeService.java:65) - tryTimes: 2 209 2018-04-25 16:24:08,534 INFO [Thread-61] (EmployeeService.java:77) - oldMoney: 167 210 2018-04-25 16:24:08,538 INFO [Thread-29] (EmployeeService.java:77) - oldMoney: 168 211 2018-04-25 16:24:08,543 INFO [Thread-23] (EmployeeService.java:65) - tryTimes: 2 212 2018-04-25 16:24:08,544 INFO [Thread-81] (EmployeeService.java:65) - tryTimes: 2 213 2018-04-25 16:24:08,544 INFO [Thread-50] (EmployeeService.java:65) - tryTimes: 2 214 2018-04-25 16:24:08,543 INFO [Thread-82] (EmployeeService.java:65) - tryTimes: 2 215 2018-04-25 16:24:08,544 INFO [Thread-78] (EmployeeService.java:65) - tryTimes: 2 216 2018-04-25 16:24:08,556 INFO [Thread-74] (EmployeeService.java:77) - oldMoney: 169 217 2018-04-25 16:24:08,572 INFO [Thread-61] (EmployeeService.java:65) - tryTimes: 2 218 2018-04-25 16:24:08,573 INFO [Thread-29] (EmployeeService.java:65) - tryTimes: 2 219 2018-04-25 16:24:08,572 INFO [Thread-97] (EmployeeService.java:65) - tryTimes: 2 220 2018-04-25 16:24:08,582 INFO [Thread-80] (EmployeeService.java:77) - oldMoney: 170 221 2018-04-25 16:24:08,583 INFO [Thread-48] (EmployeeService.java:77) - oldMoney: 171 222 2018-04-25 16:24:08,584 INFO [Thread-27] (EmployeeService.java:77) - oldMoney: 172 223 2018-04-25 16:24:08,589 INFO [Thread-32] (EmployeeService.java:77) - oldMoney: 173 224 2018-04-25 16:24:08,602 INFO [Thread-74] (EmployeeService.java:65) - tryTimes: 2 225 2018-04-25 16:24:08,608 INFO [Thread-85] (EmployeeService.java:77) - oldMoney: 174 226 2018-04-25 16:24:08,631 INFO [Thread-32] (EmployeeService.java:65) - tryTimes: 2 227 2018-04-25 16:24:08,631 INFO [Thread-27] (EmployeeService.java:65) - tryTimes: 3 228 2018-04-25 16:24:08,631 INFO [Thread-80] (EmployeeService.java:65) - tryTimes: 2 229 2018-04-25 16:24:08,632 INFO [Thread-48] (EmployeeService.java:65) - tryTimes: 2 230 2018-04-25 16:24:08,634 INFO [Thread-22] (EmployeeService.java:77) - oldMoney: 175 231 2018-04-25 16:24:08,660 INFO [Thread-85] (EmployeeService.java:65) - tryTimes: 2 232 2018-04-25 16:24:08,689 INFO [Thread-22] (EmployeeService.java:65) - tryTimes: 2 233 2018-04-25 16:24:08,696 INFO [Thread-44] (EmployeeService.java:77) - oldMoney: 176 234 2018-04-25 16:24:08,696 INFO [Thread-43] (EmployeeService.java:77) - oldMoney: 176 235 2018-04-25 16:24:08,704 INFO [Thread-13] (EmployeeService.java:77) - oldMoney: 177 236 2018-04-25 16:24:08,712 INFO [Thread-4] (EmployeeService.java:77) - oldMoney: 178 237 2018-04-25 16:24:08,722 INFO [Thread-45] (EmployeeService.java:77) - oldMoney: 179 238 2018-04-25 16:24:08,723 INFO [Thread-7] (EmployeeService.java:77) - oldMoney: 179 239 2018-04-25 16:24:08,727 INFO [Thread-44] (EmployeeService.java:65) - tryTimes: 2 240 2018-04-25 16:24:08,743 INFO [Thread-77] (EmployeeService.java:77) - oldMoney: 180 241 2018-04-25 16:24:08,748 INFO [Thread-59] (EmployeeService.java:77) - oldMoney: 181 242 2018-04-25 16:24:08,754 INFO [Thread-57] (EmployeeService.java:77) - oldMoney: 182 243 2018-04-25 16:24:08,756 INFO [Thread-45] (EmployeeService.java:65) - tryTimes: 2 244 2018-04-25 16:24:08,756 INFO [Thread-13] (EmployeeService.java:65) - tryTimes: 2 245 2018-04-25 16:24:08,757 INFO [Thread-4] (EmployeeService.java:65) - tryTimes: 2 246 2018-04-25 16:24:08,765 INFO [Thread-39] (EmployeeService.java:77) - oldMoney: 183 247 2018-04-25 16:24:08,779 INFO [Thread-66] (EmployeeService.java:77) - oldMoney: 184 248 2018-04-25 16:24:08,785 INFO [Thread-59] (EmployeeService.java:65) - tryTimes: 2 249 2018-04-25 16:24:08,785 INFO [Thread-77] (EmployeeService.java:65) - tryTimes: 2 250 2018-04-25 16:24:08,796 INFO [Thread-55] (EmployeeService.java:77) - oldMoney: 185 251 2018-04-25 16:24:08,811 INFO [Thread-62] (EmployeeService.java:77) - oldMoney: 186 252 2018-04-25 16:24:08,814 INFO [Thread-39] (EmployeeService.java:65) - tryTimes: 2 253 2018-04-25 16:24:08,814 INFO [Thread-57] (EmployeeService.java:65) - tryTimes: 2 254 2018-04-25 16:24:08,814 INFO [Thread-66] (EmployeeService.java:65) - tryTimes: 2 255 2018-04-25 16:24:08,827 INFO [Thread-94] (EmployeeService.java:77) - oldMoney: 187 256 2018-04-25 16:24:08,840 INFO [Thread-53] (EmployeeService.java:77) - oldMoney: 188 257 2018-04-25 16:24:08,840 INFO [Thread-95] (EmployeeService.java:77) - oldMoney: 188 258 2018-04-25 16:24:08,843 INFO [Thread-62] (EmployeeService.java:65) - tryTimes: 2 259 2018-04-25 16:24:08,843 INFO [Thread-55] (EmployeeService.java:65) - tryTimes: 2 260 2018-04-25 16:24:08,857 INFO [Thread-37] (EmployeeService.java:77) - oldMoney: 189 261 2018-04-25 16:24:08,872 INFO [Thread-94] (EmployeeService.java:65) - tryTimes: 2 262 2018-04-25 16:24:08,872 INFO [Thread-53] (EmployeeService.java:65) - tryTimes: 2 263 2018-04-25 16:24:08,887 INFO [Thread-15] (EmployeeService.java:77) - oldMoney: 190 264 2018-04-25 16:24:08,891 INFO [Thread-16] (EmployeeService.java:77) - oldMoney: 191 265 2018-04-25 16:24:08,902 INFO [Thread-37] (EmployeeService.java:65) - tryTimes: 2 266 2018-04-25 16:24:08,909 INFO [Thread-14] (EmployeeService.java:77) - oldMoney: 192 267 2018-04-25 16:24:08,931 INFO [Thread-16] (EmployeeService.java:65) - tryTimes: 2 268 2018-04-25 16:24:08,931 INFO [Thread-15] (EmployeeService.java:65) - tryTimes: 2 269 2018-04-25 16:24:08,960 INFO [Thread-14] (EmployeeService.java:65) - tryTimes: 2 270 2018-04-25 16:24:08,964 INFO [Thread-65] (EmployeeService.java:77) - oldMoney: 193 271 2018-04-25 16:24:08,965 INFO [Thread-42] (EmployeeService.java:77) - oldMoney: 194 272 2018-04-25 16:24:08,970 INFO [Thread-19] (EmployeeService.java:77) - oldMoney: 195 273 2018-04-25 16:24:08,989 INFO [Thread-65] (EmployeeService.java:65) - tryTimes: 3 274 2018-04-25 16:24:09,018 INFO [Thread-42] (EmployeeService.java:65) - tryTimes: 2 275 2018-04-25 16:24:09,018 INFO [Thread-19] (EmployeeService.java:65) - tryTimes: 2 276 2018-04-25 16:24:09,025 INFO [Thread-40] (EmployeeService.java:77) - oldMoney: 196 277 2018-04-25 16:24:09,056 INFO [Thread-40] (EmployeeService.java:65) - tryTimes: 3 278 2018-04-25 16:24:09,318 INFO [Thread-43] (EmployeeService.java:77) - oldMoney: 197 279 2018-04-25 16:24:09,352 INFO [Thread-43] (EmployeeService.java:65) - tryTimes: 3 280 2018-04-25 16:24:09,433 INFO [Thread-7] (EmployeeService.java:77) - oldMoney: 198 281 2018-04-25 16:24:09,473 INFO [Thread-7] (EmployeeService.java:65) - tryTimes: 3 282 2018-04-25 16:24:09,578 INFO [Thread-95] (EmployeeService.java:77) - oldMoney: 199 283 2018-04-25 16:24:09,627 INFO [Thread-95] (EmployeeService.java:65) - tryTimes: 3
可以看到,還是有一些線程會拿到相同的值,但是由於版本控制使得最終只有一根線程能夠更新成功,其它更新失敗的線程會繼續嘗試,最終能更新成功。
第三部分 總結&對比
悲觀鎖 | 樂觀鎖 | |
概念 | 查詢時直接鎖住記錄使得其它事務不能查詢,更不能更新 | 提交更新時檢查版本或者時間戳是否符合 |
語法 | select ... for update | 使用 version 或者 timestamp 進行比較 |
實現者 | 數據庫本身 | 開發者 |
適用場景 | 並發量大 | 並發量小 |
類比Java | Synchronized關鍵字 | CAS 算法 |