Java重入鎖死簡介

重入鎖死與死鎖嵌套管程鎖死很是類似。讀寫鎖兩篇文章中都有涉及到重入鎖死的問題。html

deadlock

當一個線程從新獲取讀寫鎖或其餘不可重入的同步器時,就可能發生重入鎖死。可重入的意思是線程能夠重複得到它已經持有的鎖。Java的synchronized塊是可重入的。所以下面的代碼是沒問題的:java

(譯者注:這裏提到的鎖都是指的不可重入的鎖實現,並非Java類庫中的Lock與ReadWriteLock類)segmentfault

public class Reentrant{
    public synchronized outer(){
        inner();
    }

    public synchronized inner(){
        //do something
    }
}

注意outer()和inner()都聲明爲synchronized,這在Java中這至關於synchronized(this)塊(譯者注:這裏兩個方法是實例方法,synchronized的實例方法至關於在this上加鎖,若是是static方法,則否則,更多閱讀:哪一個對象纔是鎖?)。若是某個線程調用了outer(),outer()中的inner()調用是沒問題的,由於兩個方法都是在同一個管程對象(即this)上同步的。若是一個線程持有某個管程對象上的鎖,那麼它就有權訪問全部在該管程對象上同步的塊。這就叫可重入。若線程已經持有鎖,那麼它就能夠重複訪問全部使用該鎖的代碼塊。this

下面這個鎖的實現是不可重入的:spa

public class Lock{
    private boolean isLocked = false;
    public synchronized void lock()
        throws InterruptedException{
        while(isLocked){
            wait();
        }
        isLocked = true;
    }

    public synchronized void unlock(){
        isLocked = false;
        notify();
    }
}

若是一個線程在兩次調用lock()間沒有調用unlock()方法,那麼第二次調用lock()就會被阻塞,這就出現了重入鎖死。線程

避免重入鎖死有兩個選擇:code

  1. 編寫代碼時避免再次獲取已經持有的鎖
  2. 使用可重入鎖

至於哪一個選擇最適合你的項目,得視具體狀況而定。可重入鎖一般沒有不可重入鎖那麼好的表現,並且實現起來複雜,但這些狀況在你的項目中也許算不上什麼問題。不管你的項目用鎖來實現方便仍是不用鎖方便,可重入特性都須要根據具體問題具體分析。htm


原文 Reentrance Lockout
做者 Jakob Jenkov
譯者 劉曉日
校對 丁一
via ifeve對象

相關文章
相關標籤/搜索