二進制信號量vs重入鎖
1.概述
在本教程中,我們將探討二進制信號量和可重入鎖。另外,我們將彼此進行比較,以了解哪種情況最適合常見情況。
2.什麼是二進制信號量?
二進制信號量提供了對單個資源的訪問的信令機制。換句話說,二進制信號量提供了互斥性,該互斥性僅允許一個線程一次訪問關鍵部分。
為此,它僅保留一個許可證可供訪問。因此,二進制信號量只有兩種狀態:一個許可可用或零許可可用。
讓我們使用Java中可用的Semaphore
類討論二進制信號量的簡單實現:
Semaphore binarySemaphore = new Semaphore(1);
try {
binarySemaphore.acquire();
assertEquals(0, binarySemaphore.availablePermits());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
binarySemaphore.release();
assertEquals(1, binarySemaphore.availablePermits());
}
在這裡,我們可以看到, acquire
方法將可用許可證減少了一個。同樣, release
方法將可用許可證增加了一個。
此外, Semaphore
類提供fairness
參數。當設置為true
, fairness
參數確保請求線程獲得許可的順序(基於它們的等待時間):
Semaphore binarySemaphore = new Semaphore(1, true);
3.什麼是可重入鎖?
可重入鎖是一種互斥機制,該機制允許線程(多次)重新進入資源鎖,而不會出現死鎖情況。
進入鎖的線程每次都會將保持計數增加一。同樣,請求解鎖時,保留計數會減少。因此,資源被鎖定,直到計數器返回零為止。
例如,讓我們看一下使用Java中提供的ReentrantLock
類的簡單實現:
ReentrantLock reentrantLock = new ReentrantLock();
try {
reentrantLock.lock();
assertEquals(1, reentrantLock.getHoldCount());
assertEquals(true, reentrantLock.isLocked());
} finally {
reentrantLock.unlock();
assertEquals(0, reentrantLock.getHoldCount());
assertEquals(false, reentrantLock.isLocked());
}
在這裡, lock
方法將保持計數增加一併鎖定資源。類似地,如果保持計數為零,那麼unlock
方法會減少保持計數並解鎖資源。
當線程重新進入鎖時,它必須請求解鎖相同的次數才能釋放資源:
reentrantLock.lock();
reentrantLock.lock();
assertEquals(2, reentrantLock.getHoldCount());
assertEquals(true, reentrantLock.isLocked());
reentrantLock.unlock();
assertEquals(1, reentrantLock.getHoldCount());
assertEquals(true, reentrantLock.isLocked());
reentrantLock.unlock();
assertEquals(0, reentrantLock.getHoldCount());
assertEquals(false, reentrantLock.isLocked());
與Semaphore
類類似, ReentrantLock
類也支持fairness
參數:
ReentrantLock reentrantLock = new ReentrantLock(true);
4.二進制信號量與可重入鎖定
4.1。機制
二進制信號量是一種信號機制,而可重入鎖是一種鎖定機制。
4.2。所有權
沒有線程是二進制信號量的所有者。但是,成功鎖定資源的最後一個線程是可重入鎖的所有者。
4.3。性質
二進制信號量本質上是不可重入的,這意味著同一線程無法重新獲取關鍵部分,否則將導致死鎖情況。
另一方面,重入鎖本質上允許通過同一線程多次重入鎖。
4.4。靈活性
二進制信號量通過允許自定義實現鎖定機制和死鎖恢復來提供更高級別的同步機制。因此,它賦予了開發人員更多的控制權。
但是,可重入鎖定是具有固定鎖定機制的低級同步。
4.5。修改
二進制信號量支持諸如等待和信號(在Java的Semaphore
類的情況下為獲取和釋放)之類的操作,以允許任何進程修改可用的許可。
另一方面,只有鎖定/解鎖資源的同一線程才能修改可重入鎖定。
4.6。死鎖恢復
二進制信號量提供了一種非所有權釋放機制。因此,任何線程都可以釋放對二進制信號量進行死鎖恢復的許可。
相反,在重入鎖的情況下,很難實現死鎖恢復。例如,如果可重入鎖的所有者線程進入睡眠或無限等待狀態,則將無法釋放資源,從而導致死鎖。
5.結論
在這篇簡短的文章中,我們探討了二進制信號量和可重入鎖。
首先,我們討論了二進制信號量和可重入鎖的基本定義,以及Java的基本實現。然後,我們根據一些參數(例如機制,所有權和靈活性)相互比較。
我們當然可以得出結論,二進制信號量為互斥提供了一種基於非所有權的信號機制。同時,它可以進一步擴展以提供具有輕鬆死鎖恢復的鎖定功能。
另一方面,可重入鎖提供了基於所有者鎖定功能的可重入互斥,可作為簡單的互斥鎖使用。
像往常一樣,可以在GitHub上找到源代碼。