Mysql鎖機制--樂觀鎖 & 悲觀鎖


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 中的業務邏輯:

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
View Code

可以看到,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
View Code

可以看到,還是有一些線程會拿到相同的值,但是由於版本控制使得最終只有一根線程能夠更新成功,其它更新失敗的線程會繼續嘗試,最終能更新成功。

第三部分 總結&對比

  悲觀鎖 樂觀鎖
概念 查詢時直接鎖住記錄使得其它事務不能查詢,更不能更新 提交更新時檢查版本或者時間戳是否符合
語法 select ... for update 使用 version 或者 timestamp 進行比較
實現者 數據庫本身 開發者
適用場景 並發量大 並發量小
類比Java Synchronized關鍵字 CAS 算法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM