synchronized可重入鎖

什麼是可重入鎖?它有什麼作用?

可重入鎖,也叫做遞歸鎖,指的是在同一線程內,外層函數獲得鎖之後,內層遞歸函數仍然可以獲取到該鎖。
說白了就是同一個線程再次進入同樣代碼時,可以再次拿到該鎖。
它的作用是:防止在同一線程中多次獲取鎖而導致死鎖發生。
在java的編程中synchronized 和 ReentrantLock都是可重入鎖。

案例實戰:基於synchronized下訂單的可重入鎖

業務場景:模仿下訂單操作,先減庫存,再插入訂單表。

步驟1:庫存加鎖,訂單也加鎖

public class SynchronizedDemo {
    //模擬庫存100
    int count=100;
    public synchronized void operation(){
        log.info("第一層鎖:減庫存");
        //模擬減庫存
        count--;
        add();
        log.info("下訂單結束庫存剩餘:{}",count);
    }

    private synchronized void add(){
        log.info("第二層鎖:插入訂單");
        try {
            Thread.sleep(1000*10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

步驟2:加個測試類

public class SynchronizedController {

    SynchronizedDemo synchronizedDemo=new SynchronizedDemo();


    @GetMapping(value = "/lock1")
    public void lock1(String key) {
        log.info("-------用戶{}開始下單--------",key);
        this.synchronizedDemo.operation();

    }

}

步驟3:測試體驗

2020-03-08 10:47:52.038  INFO 75593 --- [nio-9090-exec-9] c.a.r.controller.SynchronizedController  : -------用戶1開始下單--------
2020-03-08 10:47:52.039  INFO 75593 --- [nio-9090-exec-9] c.agan.redis.Reentrant.SynchronizedDemo  : 第一層鎖:減庫存
2020-03-08 10:47:52.039  INFO 75593 --- [nio-9090-exec-9] c.agan.redis.Reentrant.SynchronizedDemo  : 第二層鎖:插入訂單
2020-03-08 10:47:54.606  INFO 75593 --- [io-9090-exec-10] c.a.r.controller.SynchronizedController  : -------用戶2開始下單--------
2020-03-08 10:47:56.613  INFO 75593 --- [nio-9090-exec-1] c.a.r.controller.SynchronizedController  : -------用戶3開始下單--------
2020-03-08 10:48:02.047  INFO 75593 --- [nio-9090-exec-9] c.agan.redis.Reentrant.SynchronizedDemo  : 下訂單結束庫存剩餘:99
2020-03-08 10:48:02.047  INFO 75593 --- [nio-9090-exec-1] c.agan.redis.Reentrant.SynchronizedDemo  : 第一層鎖:減庫存
2020-03-08 10:48:02.047  INFO 75593 --- [nio-9090-exec-1] c.agan.redis.Reentrant.SynchronizedDemo  : 第二層鎖:插入訂單
2020-03-08 10:48:12.057  INFO 75593 --- [nio-9090-exec-1] c.agan.redis.Reentrant.SynchronizedDemo  : 下訂單結束庫存剩餘:98
2020-03-08 10:48:12.057  INFO 75593 --- [io-9090-exec-10] c.agan.redis.Reentrant.SynchronizedDemo  : 第一層鎖:減庫存
2020-03-08 10:48:12.057  INFO 75593 --- [io-9090-exec-10] c.agan.redis.Reentrant.SynchronizedDemo  : 第二層鎖:插入訂單
2020-03-08 10:48:22.064  INFO 75593 --- [io-9090-exec-10] c.agan.redis.Reentrant.SynchronizedDemo  : 下訂單結束庫存剩餘:97

通過測試結果:
1.發送了3次請求,springboot啓用了3條線程來處理,分別是nio-9090-exec-9 io-9090-exec-10 nio-9090-exec-1
2.nio-9090-exec-9線程,在operation()方法內能正常調用add(),即證明了Synchronized是可重入鎖
3.只有當nio-9090-exec-9線程執行完後,才能執行io-9090-exec-10 nio-9090-exec-1,爲什麼?
因爲線程之間的請求都被鎖住了,也證明了Synchronized在不同的線程之間是不可重入的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章