這是我所引用的報價的解釋。我希望這是可以理解的,並且實際上符合撰寫原始答案的人的意圖。
比方說你有一個需要由一個互斥被保護的數據結構。您可以選擇如何處理與這些對象相關的關鍵部分。這些選項也可以對一個線程可能需要如何表現的同時獲得多個對象的鎖的影響:
使用每個對象一個互斥體:
struct foo {
mutex mux;
// important data fields...
};
這樣做的有利於處理不同對象的線程不會產生爭用。如果一個線程需要處理多個對象,同時爲它們保留鎖定(我認爲這是「集合合」的含義),所以不需要遞歸互斥鎖。但是,需要注意避免死鎖。
具有每個對象指的是遞歸互斥體可與其它對象共享:
struct foo {
recursive_mutex* pmux;
// important data fields...
};
由於兩個對象可能實際上與單個互斥相關聯,如果線程1試圖鎖定對象A和線程2在對象A和B共享相同的互斥鎖時同時嘗試鎖定對象B,其中一個線程將阻塞,直到另一個線程釋放互斥鎖爲止。由於互斥鎖是遞歸的,單個線程可以鎖定多個對象,即使它們共享相同的互斥鎖。請注意,關於死鎖仍存在相同的警告。
的(可能)的優勢,該方案在第一的是,如果一個線程在同一時間鎖定幾個對象有一定的概率,一些在集中的對象將共享一個互斥體。一旦線程鎖定其中一個對象,理論上來說,嘗試鎖定下一個對象時阻塞的可能性就會降低。然而,我認爲在實踐中,證明你會獲得這種好處可能是相當困難的,除非你能真正表徵你的線程的鎖定行爲和他們將要鎖定的對象集合(並設置互斥鎖共享來鏡像模型)。
該引用中的最後一項基本上是指在上述場景中使用非遞歸鎖。在這種情況下,您需要防止線程嘗試「重新鎖定」互斥鎖(當然,這不能用非遞歸互斥鎖來完成),因此線程必須以某種方式比較它將要關閉的鎖獲取它已獲取的鎖以確定它是否應該獲取該對象上的鎖。如果涉及的對象不止一個,這可能會變成一個複雜的場景,以確保線程獲得完全正確的一組鎖。
struct foo {
mutex* pmux; // pointer to (possibly shared) non-recursive mutex
// important data fields...
};
// a set of objects a thread needs to work on in a critical section
// the objects possibly share non-recursive mutexes
struct foo* pA;
struct foo* pB;
struct foo* pC;
// acquire the necessary locks on all three objects:
mutex_lock(pA->pmux);
if (pB->pmux != pA->pmux) mutex_lock(pB->pmux);
if ((pC->pmux != pA->pmux) && (pC->pmux != pB->p-mux)) mutex_lock(pC->pmux);
// releasing the set of mutexes is similar
不用手動獲取互斥內聯,它很可能是最好把它們傳遞給管理的確保任何重複被忽略的複雜功能。和以前的計劃一樣,避免死鎖仍然需要解決。
我知道標題是可悲的,但我無法確定一個更好的「特定」標題。 –