title: How do I efficiently support both item- and collection-level locking?
body: <p>I have an application has a collection of domain objects that need to be 
  updated in real-time. Several threads can take action that modify the items in 
  this collection and must do so safely. The current approach is rather 
  simplistic, taking essentially a global lock before making any changes. 
  More or less something like the following:</p>
  
  <pre><code>private readonly object lockObject = new object();
  private Dictionary&lt;int, Widget&gt; items;
  
  private void UpdateAllWidgets()
  {
      lock (this.lockObject)
      {
          // Update all the widgets. No widgets should be permitted to be 
          // updated while this is running.
      }
  }
  
  private void UpdateWidget(int widgetId)
  {
      lock (this.lockObject)
      {
          // Update the widget with id = widgetId. I want to me able to 
          // update other widgets at the same time, however.
      }
  }
  </code></pre>
  
  <p>I am now running into problems with performance because the lock is too coarse.
  I would like to be able to take item-level locks while a single item is being
  updated (allowing other items to be updated at the same time), but still be able
  to take a collection-level lock when necessary. So the behavior would look like
  the following:</p>
  
  <pre><code>Thread 1: UpdateWidget(1);
  Thread 2: UpdateWidget(2);  // This can run before UpdateWidget(1) 
                              // completes.
  
  Thread 1: UpdateWidget(1);
  Thread 2: UpdateAllWidgets();  // This has to wait for UpdateWidget(1)
  Thread 3: UpdateWidget(2);  // This has to wait for UpdateAllWidgets()
  Thread 4: UpdateWidget(3);  // This has to wait for UpdateAllWidgets(), but
                              // not UpdateWidget(2)
  </code></pre>
  
  <p><strong>Any ideas on a lock structure that would support this?</strong> The example above is 
  necessary a simplified version, but we have already ruled out 
  ConcurrentDictionary has being insufficient. The actions taken in, for example, 
  UpdateWidget, are more than just simple in-place updates. They could involve database updates that impact that item, etc.</p>