2011-06-14 38 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