Java中如何理解可重入鎖的概念?爲什麼ReentrantLock不手動釋放鎖會造成死鎖?

之前有文章說過,synchronized和ReenTrantLock都是可重入鎖,那麼什麼是可重入鎖?

可重入鎖從字面意思就比較容易理解,自己獲取了鎖以後,可以再次獲取該鎖(重入)就叫可重入鎖,同一個線程每次獲取鎖,鎖計數器都自增1,所以要等到鎖的計數器下降爲0時才能釋放鎖。

我們就以之前賣票的例子進行講解,因爲synchronized加鎖和解鎖的過程是自動進行,所以不會造成死鎖,而ReentrantLock加鎖和解鎖的過程需要手動,所以如果加鎖和釋放鎖次數不一,會導致死鎖,我們看代碼:

public class FairLocked implements Runnable {
	private int seatNumber = 100;
	/**
	 * 公平鎖實現 ReentrantLock構造方法中設置爲true:代表公平鎖
	 * 
	 * 設置爲false:代表非公平鎖 默認也是非公平鎖
	 * 
	 */
	/** private ReentrantLock lock = new ReentrantLock(true); */

	/** private ReentrantLock lock = new ReentrantLock(false); */
	private ReentrantLock lock = new ReentrantLock();

	@Override
	public void run() {
		while (true) {
			try {
				lock.lock();
				if (seatNumber > 0) {
					Thread.sleep(100);
					--seatNumber;
					System.out.println(Thread.currentThread().getName() + "佔用1個座位,還剩餘 " + seatNumber + "個座位");
				} else {
					System.out.println(Thread.currentThread().getName() + ":不好意思,票賣完了!");
					break;
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			} finally {

				/** lock.unlock(); */
			}
		}
	}

	public static void main(String[] args) {
		FairLocked rlbr = new FairLocked();
		Thread t1 = new Thread(rlbr, "A窗口");
		Thread t2 = new Thread(rlbr, "B窗口");
		t1.start();
		t2.start();
	}
}

那麼,可重入鎖的原理是什麼呢?

之前我們也有提到過一個詞,叫鎖計數器。重入鎖實現機制就是基於一個鎖關聯一個線程持有者和計數器,當計數器爲0時表示該鎖沒有被任何線程持有,那麼任何線程都可能獲得該鎖而調用相應的方法;當某一線程請求成功後,JVM會記下鎖的線程持有者,同時將鎖計數器置爲1;此時其它線程請求該鎖,就只能等待,而該鎖持有者卻可以再次請求鎖,同時鎖計數器會遞增,當線程退出同步代碼塊時,計數器會遞減,直至鎖計數器爲0,則釋放。

所以,如果ReentrantLock不手動釋放鎖,就會造成死鎖。

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