2009-04-27 71 views
1

我最近被一位剛剛開始使用線程的朋友問到,純粹是爲了鎖定目的還是僅僅鎖定您引用的對象而使用次級對象。我不得不承認我不知道,誰能告訴我?我會嘗試與一對夫婦的代碼片段演示:鎖定指定對象和鎖定輔助對象有什麼區別?

第一種方法:

List<string> data = new List<string>(); 
object datalock = new object(); 

void main() 
{ 
    lock(datalock) 
    { 
     if (data.contains("SomeSearchString")) 
     { 
      //Do something with the data and then remove it 
     } 
    } 
} 

方法二:

List<string> data = new List<string>(); 

void main() 
{ 
    lock(data) 
    { 
     if (data.contains("SomeSearchString")) 
     { 
      //Do something with the data and then remove it 
     } 
    } 
} 

是否有顯著差異或者是這個到個人編碼風格?如果存在顯着差異,任何人都可以解釋它是什麼?

我確實遇到過另一個問題[Difference between lock(locker) and lock(variable_which_I_am_using)],其中的答案暗示這兩個都是等價的,但如果是這樣的話,哪個最好用,爲什麼?

我見過很多遍佈網絡的例子,我傾向於使用第一種方法作爲個人選擇的問題,但我想知道使用第二種方法的優點是什麼。

回答

5

最大的區別是,第二個對象,只有你的代碼知道有來自其他代碼(不是你的)鎖定對意想不到的後果(死鎖,脈衝/等待陷阱等)沒有風險主要對象(通常可用於其他代碼)。

IMO,也許CLR團隊會做的更好的明確Lock類型 - 或者Monitor應該已經無靜電等

+0

我只是在輸入那個... 我要添加的唯一東西是鎖定主對象確實允許子類知道他們正在做什麼來參與超類鎖定策略,這會提供稍微更大的靈活性 - 但面臨不知道自己在做什麼的消費者可能導致更多問題的風險。 – 2009-04-27 22:16:56

1

最重要的一點已涵蓋馬克,但我更喜歡第一種模式,因爲它還打開了爲讀寫鎖定分隔對象的範圍,或者可能對您的特定用途有用的任何其他級別的粒度。

+0

我想它也允許目標對象的子方法在鎖被放置時仍然被訪問,而不必等待鎖被釋放。 – BenAlabaster 2009-04-27 22:27:20

0

從根本上說,沒有區別。如果所有線程不安全操作鎖定在同一個對象上,則沒有區別。然而,從實施的角度來看,可能會有差異。如果其他線程需要訪問需要獨佔鎖定的對象,則必須確保使該同步對象可用並清除哪個對象需要鎖定。

另一方面,在某些情況下,您可能實際上將值分配給鎖塊內的不同內容。在這種情況下,你顯然需要鎖定一個不相關的對象。

歸結到一點,無論是個人喜好和可維護性(被鎖定需要第二個對象,一個壞主意,或者兩者都不對?)

0

使用不同的對象鎖定允許多個同步的粒度和性能。如果您鎖定同一個對象,則一個操作可能會不必要地阻塞另一個對象。如果你使用lock(this),所有的併發操作都必須等到擁有該鎖的那個操作釋放它。但是,這可能不是必需的,因爲某些操作可能不會訪問相同的資源。所以你不必要地鎖定它們,從而傷害到性能。相反,對不同的共享資源組使用不同的同步對象,並讓您的操作使用相應的鎖來訪問他們需要訪問的資源。