2011-06-14 57 views
3

我使用ReaderWriterLock類來鎖定一個Quotes集合,它是一個SortedDictionary。我正在考慮使用while循環,直到線程可以獲取讀寫器鎖定,以防寫入時暫時鎖定。第一個問題,我的測試工作正常,但這種方法有什麼缺點。第二個問題,這樣做的最佳/最佳實踐方式是什麼?是否可以(避免死鎖,陷阱等...)嘗試獲取睡眠循環中的鎖?

 public void RequestQuote(string symbol, QuoteRequestCallback qrc) 
     { 
      // add the call back on a list and take care of it when the quote is available 
      while (!AcquireReaderLock(100)) Thread.Sleep(150); 
      if (Quotes.ContainsKey(symbol)) 
      { 
       qrc(Quotes[symbol]); 
       rwl.ReleaseReaderLock(); 
      } 
      else 
      { 
       rwl.ReleaseReaderLock(); 
       lock (requestCallbacks) 
        requestCallbacks.Add(new KeyValuePair<string, QuoteRequestCallback>(symbol, qrc)); 
       // request symbol to be added 
       AddSymbol(symbol); 
      } 
     } 


     private bool AquireReaderLock(int ms) 
     { 
      try 
      { 
       rwl.AcquireReaderLock(ms); 
       return true; 
      } 
      catch (TimeoutException) 
      { 
       return false; 
      } 
     } 

     private bool AquireWriterLock(int ms) 
     { 
      try 
      { 
       rwl.AcquireWriterLock(ms); 
       return true; 
      } 
      catch (TimeoutException) 
      { 
       return false; 
      } 
     } 
+1

如果AcquireReaderLock永不返回true,會發生什麼情況?你的程序是否保持一致的狀態? – 2011-06-15 00:02:15

+0

如果AcquireReaderLock永遠不會返回true,則RequestQuote會掛起無限循環。我將在編輯中粘貼代碼。 – bkarj 2011-06-15 00:09:06

+0

嗯,我的觀點是你不能認爲它會。所以,如果超過了一定的重試次數,你需要一些機制來打破你的等待循環。 – 2011-06-15 00:10:35

回答

2

你有與AcquireReaderLock()方法之前鎖定第二一段代碼鎖requestCallbacks?如果是這樣,它可能會因此而死鎖。

添加循環和睡眠延遲以避免死鎖在一般情況下不起作用。嚴格的hierarchy of lock acquisition將在工作的一般情況下。

+0

不,我沒有requestCallbacks與AcquireReaderLock同時被鎖定。你能舉一個嚴格等級的例子嗎?你失去了我。 – bkarj 2011-06-15 00:19:18

+0

@Behrooz,我添加了一個鎖體層次體面描述的鏈接;基本上,你要確保你總是在其他種類的鎖上獲得某些鎖(或各種鎖),並以相反的順序釋放它們。你可以決定你總是先鎖定你的回調,然後是你的報價(或其他方式);或者您可以決定按照最低指針值的順序鎖定您的資源;或者,如果鎖高度競爭,可能只需用一個鎖代替兩個鎖,並避免這種死鎖。 – sarnold 2011-06-15 00:28:05

+0

@Behrooz,但如果這是整個系統中同時鎖定這兩個鎖的唯一代碼,那麼你可能已經完成了。 :) – sarnold 2011-06-15 00:28:33

2

我不太明白你想達到什麼目的。 ReaderWriterLockSlim(我會用)已經沒什麼特別的了 - 它不需要額外的旋轉,你只是在浪費資源。 a)如果找不到或更好的符號,則將R-Lock推廣到W-Lock,將R和W訪問分爲不同的方法。 b)不要提供從受保護區域內調用未知代碼的可能性

public void RequestQuote(string pS, QuoteRequestCallback pQrc) { 
    Quote tQ; 
    // acquire/release ReadLock inside TryGet 
    if (TryGetQuote(pS, out tQ)) { 
     pQrc(tQ); 
    } else { 
     // acquire/release WriteLock inside AddQuote 
     // remark: I left the other collection 
     // out since it seems unrelated to the actual problem 
     AddQuote(new KeyValuePair(...)); // as above 
    } 
} 
+0

我不知道ReaderWriterLockSlim。閱讀並更改我的實施。效果很好。謝謝 – bkarj 2011-06-15 16:30:52

+0

好吧,它們在概念上並沒有什麼不同,它只是邏輯上更好更高效的實現。其他評論更重要...... – 2011-06-16 08:12:37