2017-10-09 175 views

回答

0

在此上下文中,重入意味着線程可以多次調用同一個鎖上的獲取,而在第二次或第三次調用時不會阻止。但是,它必須平衡所有采集和相同數量的發佈。這StackOverflow的職位會談更多關於重入鎖:

What is the Re-entrant lock and concept in general?

具體到館長,這裏是什麼文件對此有什麼看法不同的鎖:

Shared Re-entrant lock aka InterProcessMutex

public void acquire()
獲取互斥鎖 - 阻止,直到它的可用的 。注意:同一個線程可以重新調用獲取。每個 調用獲取必須通過調用來平衡釋放()

Shared lock (non-reentrant) aka InterProcessSemaphoreMutex

public void acquire()
獲取互斥鎖 - 阻塞,直到它可用。必須通過調用release()來平衡。

在下面的例子中,如果lock是一個可重入鎖,那麼下面的代碼將運行到完成並正常工作。如果lock不是一個重入鎖,線程將同時撥打第二lock.acquire()死鎖:

lock.acquire(); 
lock.acquire(); 
doWork(); 
lock.release(); 
lock.release(); 

折返鎖往往是多一點昂貴的實現,但更容易使用。

上面的模式經常發生,當你的API有多個公共方法必須鎖定,但你的實現有公共方法調用其他公共方法。您可以通過讓公共方法鎖定並僅鎖定來避免這種情況,然後調用一個私有方法,假定它總是在鎖的下方執行;那麼你的私有方法可以調用其他私有方法而不需要多次獲取鎖。

編輯解決@ Randgalt的評論:

館長的InterProcessMutex要求獲取鎖釋放它相同的線程。 InterProcessSemaphoreMutex沒有。也許你誤解了我寫的內容?也許我不清楚?不知道。無論如何,情況就是這樣。

這顯然是錯誤的;既不鎖定,也不允許你從獲取鎖的線程以外的線程釋放它。此外,在這種情況下,這仍然與「什麼是重入」問題無關 - 在這種情況下,重入是您是否可以在同一線程上多次調用同一個鎖上的獲取。

InterProcessMutex.release()

public void release()
如果調用線程是收購它同一個線程執行互斥的一個釋放。如果線程已經多次調用獲取,那麼當此方法返回時,互斥量仍將保持不變。

InterProcessSemaphoreMutex.release()

public void release()
如果調用線程是獲取了它在同一個線程執行互斥的一個釋放。

強調添加。這兩個鎖都不允許你從擁有鎖的線程以外的任何線程解鎖它 - 這是有道理的,因爲這兩個鎖都是互斥鎖,並且這是互斥鎖的屬性之一。

+0

感謝您的迴應。非重入鎖看起來更容易出現死鎖。是否有使用情況下最好使用不可重入的重入鎖? – Glide

+0

@Glide - 他們可能會有更好的表現。 – antiduh

+0

很多時候,您無法從獲取它的同一個線程中釋放鎖(或者您不在乎)。在這些情況下,非折返鎖是選擇。 – Randgalt

1

我是Apache Curator的主要作者。不管文檔可能會或可能不會說什麼,爲了記錄,爲這兩個類中的每一個都提供確切的用例。

InterProcessMutex

InterProcessMutex當你需要能夠在重入的方式來鎖定應該使用。這意味着一個給定的線程被稱爲「擁有」一次獲得的鎖,並且如果需要可以再次鎖定它。如果線程將鎖對象傳遞給其他方法,如果鎖已被獲取或不需要關心,這非常有用。請注意,這也意味着只有擁有的線程才能釋放鎖。這裏有一個例子:

InterProcessMutex lock = new InterProcessMutex(...); 

if (!lock.acquire(...)) ... // if acquire failed: throw, return, etc 
try { 
    doWork(lock); // doWork() can safely call lock.acquire() again on the lock 
} finally { 
    lock.release(); 
} 

一旦獲得,如果鎖在不同的線程比用來獲取鎖IllegalMonitorStateException被拋出的一個釋放。

InterProcessSemaphoreMutex

InterProcessSemaphoreMutex是鎖不請記獲得它的線程中的一個寬鬆的版。它具有更簡單的語義。每個InterProcessSemaphoreMutex實例只能獲取一次,並且必須通過發佈(在任何線程中)進行平衡。即

InterProcessSemaphoreMutex lock = new InterProcessSemaphoreMutex(...); 

lock.acquire(); 
lock.acquire(); // this will block forever 

我希望這有助於。如果文檔需要澄清,我們將非常感謝帶有改進的合併請求。

+0

你的「重入」定義與社區接受的定義不同。參考https://stackoverflow.com/questions/1312259/例如:「*一個可重入鎖是一個進程可以多次聲明鎖而不會自行阻塞的地方。*」 – antiduh

+0

@antiduh InterProcessMutex符合該定義。這是變得乏味。 – Randgalt