在Java的ReentrantLock構(gòu)造函數(shù)中提供了兩種鎖:創(chuàng)建公平鎖和非公平鎖(默認(rèn)),。代碼如下:
public ReentrantLock() { sync = new NonfairSync(); }
public ReentrantLock(boolean fair) { 在公平的鎖上,,線程按照他們發(fā)出請求的順序獲取鎖,,但在非公平鎖上,,則允許‘插隊(duì)’:當(dāng)一個線程請求非公平鎖時,如果在發(fā)出請求的同時該鎖變成可用狀態(tài),,那么這個線程會跳過隊(duì)列中所有的等待線程而獲得鎖,。 非公平的ReentrantLock 并不提倡 插隊(duì)行為,但是無法防止某個線程在合適的時候進(jìn)行插隊(duì),。 在公平的鎖中,,如果有另一個線程持有鎖或者有其他線程在等待隊(duì)列中等待這個所,那么新發(fā)出的請求的線程將被放入到隊(duì)列中,。而非公平鎖上,,只有當(dāng)鎖被某個線程持有時,新發(fā)出請求的線程才會被放入隊(duì)列中,。 非公平鎖性能高于公平鎖性能的原因: 在恢復(fù)一個被掛起的線程與該線程真正運(yùn)行之間存在著嚴(yán)重的延遲,。 假設(shè)線程A持有一個鎖,并且線程B請求這個鎖,。由于鎖被A持有,,因此B將被掛起。當(dāng)A釋放鎖時,,B將被喚醒,,因此B會再次嘗試獲取這個鎖。與此同時,,如果線程C也請求這個鎖,,那么C很可能會在B被完全喚醒之前獲得、使用以及釋放這個鎖,。這樣就是一種雙贏的局面:B獲得鎖的時刻并沒有推遲,,C更早的獲得了鎖,并且吞吐量也提高了,。 當(dāng)持有鎖的時間相對較長或者請求鎖的平均時間間隔較長,,應(yīng)該使用公平鎖,。在這些情況下,插隊(duì)帶來的吞吐量提升(當(dāng)鎖處于可用狀態(tài)時,,線程卻還處于被喚醒的過程中)可能不會出現(xiàn),。 |
|