2010-11-03 55 views
4
void MethodA() 
{ 
    Monitor.Enter(this); 
    if(someCondition) 
    { 
     Monitor.Exit(this); 
     // This point 
     MethodB(); 
    } 
    else 
    { 
     // Set some values only 
Monitor.Exit(this); 
    } 
} 

如果我有上述方法,其可以在多線程調用:適當使用Monitor.Exit的

  • 假定線程1處於//This point
  • 另一個線程進入Monitor.Enter而線程1仍在//This point
  • 這會停止MethodB被執行嗎?如果是的話,有沒有辦法讓MethodB執行。

我需要執行MethodB()因爲我不能等待MethodB釋放MethodA之前完成之前釋放MethodA。另外,我無法在新線程中啓動MethodB

+0

如果發生異常鎖永遠不會被釋放,只能在'try .. finally'中使用它 – Andrey 2010-11-03 16:37:06

回答

1

因爲someCondition沒有作爲參數傳遞,所以我只能假設someCondition隨時可能會改變(可能是一個實例變量)。所以,我會寫的代碼是這樣的:

void MethodA() 
{ 
    if (someCondition) 
    { 
     bool conditionReached = false; 

     Monitor.Enter(this); 
     try 
     { 
      if (someCondition) 
      { 
       conditionReached = true; 
      } 
     } 
     finally 
     { 
      Monitor.Exit(this); 
     } 

     if (conditionReached) 
     { 
      MethodB(); 
     } 
    } 
} 

如果沒有,比本地聲明condition以前的答案會適合你。

+0

這是我的情況!謝謝!! – SimpleOne 2010-11-03 18:02:13

+1

在原始代碼中,該鎖專門用於someCondition的評估,而此代碼將在鎖之外進行評估。如果條件爲false,這種雙重檢查方法可避免輸入鎖,但如果條件爲false,則原始代碼實際上在鎖的範圍內做了某些操作。最後,由於在someCondition的第一次評估中缺乏記憶障礙,「雙重檢查」方法也很容易出現罕見的種族故障。鎖定隱式強加內存屏障。 – 2010-11-03 18:26:05

+0

丹是對的。除了它與原來的行爲不同之外,它還有一個微妙的記憶障礙問題。 – 2010-11-03 18:51:05

8

撇開使用「這個」作爲一個鎖(不好的做法,因爲它公開曝光鎖定)的問題,這種形式是更清潔和更安全(版本中,如果異常被拋出鎖):

void MethodA() 
{ 
    bool condition; 
    lock(this) 
    { 
    condition = someCondition; 
    if(!condition) 
    { 
     // Set some values only 
    } 
    } 
    if (condition) 
     MethodB(); 
} 

要回答您的具體問題,即使其他內容獲取了鎖,此代碼和原始代碼也會執行MethodB。

+0

這也是一個很好的答案,所以感謝您的幫助! – SimpleOne 2010-11-03 18:12:00