線程執行synchronized同步代碼塊時再次重入該鎖過程中拋異常,是否會釋放鎖


 一個線程執行synchronized同步代碼時,再次重入該鎖過程中,如果拋出異常,會釋放鎖嗎?

如果鎖的計數器為1,拋出異常,會直接釋放鎖;

那如果鎖的計數器為2,拋出異常,會直接釋放鎖嗎?

來簡單測試一下

 

@Slf4j
public class SynchronizedExceptionRunnable implements Runnable {

    private volatile boolean flag = true;

    @Override
    public void run() {
        synchronized (this) {
            if (flag) {
                //讓先啟動的線程先執行異常方法methodB后,flag==false,並且拋出異常線程停止,直接釋放鎖,不會執行后面的代碼;
                methodB();
            } else {
                //后啟動的線程再獲取鎖,進入if-else,再獲取鎖執行methodA
                methodA();
            }
            log.info("{}:if-else end!",Thread.currentThread().getName());
        }
    }

    public synchronized void methodA(){
        log.info("ThreadName:{}----methodA", Thread.currentThread().getName());
    }

    public synchronized void  methodB() {
        flag = false;
        log.warn("ThreadName:{}----methodB will throw a exception!",Thread.currentThread().getName());

        //如果把下面這行拋異常的代碼注釋掉,會執行下面的線程睡眠5秒和最后的日志代碼
        //如果不注釋,會拋出異常,不在執行后面的代碼,並且釋放鎖,methodA方法就會執行
        int a = 1/0;


        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("ThreadName:{}----methodB End!",Thread.currentThread().getName());
    }
}

 

啟動類

 

public class Main {
    public static void main(String[] args) {
        SynchronizedExceptionRunnable runnable = new SynchronizedExceptionRunnable();

        Thread thread1 = new Thread(runnable,"杯子");
        Thread thread2 = new Thread(runnable,"人");
        thread1.start();
        thread2.start();
    }
}

 

執行結果如下圖:

 

結果分析

當“杯子”線程獲取到鎖,鎖的計數器為1,因為哨兵flag的原因,先獲取到鎖的線程調用方法methodB,會再次獲取鎖(因為synchronized是可重入鎖),此時鎖的計數器為2,然后執行methodB,該方法會拋出異常,鎖的計數器直接置為0,直接釋放鎖;

然后“人”線程獲取到鎖,鎖的計數器為1,由於flag在methodB中被設置為false,調用沒有異常的methodA,會再次獲取鎖,此時鎖的計數器為2,執行完methodA,鎖的計數器-1,此時鎖的計數器為1,再執行完run方法中的if-else,打印日志,最后釋放鎖。

 

如果不拋異常,是什么情況呢?我們把拋異常的代碼int a = 1/0 注釋掉。執行結果如下:

這個結果大家肯定清楚,就不在贅述。

 

總結

所以如果鎖的計數器為2,執行過程中拋出異常,鎖的計數器直接置為0,會直接釋放鎖!

應該是一個線程,如果執行同步代碼塊過程中拋出異常未捕獲,會立即終止,退出同步代碼塊,並且釋放鎖,不會執行后續代碼。

最核心的就是拋了異常,線程內部如果沒處理,線程會直接停止!


免責聲明!

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



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