title: .NET4.0: Thread-Safe Manner of Updating A Dictionary and Its Values
body: <p>I have a static Dictionary that I want to safely update.  Initially, the dictionary will be empty, but over the lifetime of app, it will have new values added to it.  Also, the integer values will act as individual counters that can increment and decrement.</p>
  
  <pre><code>private static Dictionary&lt;string, int&gt; foo = new Dictionary&lt;string, int&gt;();
  
  public static void Add(string bar)
  {
      if (!foo.ContainsKey(bar))
          foo.Add(bar, 0);
  
      foo[bar] = foo[bar] + 1;
  }
  
  
  public static void Remove(string bar)
  {
      if (foo.ContainsKey(bar))
      {
          if (foo[bar] &gt; 0)
              foo[bar] = foo[bar] - 1;
      }
  }
  </code></pre>
  
  <p>I've been reading up on the <a href="http://msdn.microsoft.com/en-us/library/system.threading.interlocked.aspx" rel="nofollow">Interlocked class</a> as a means to provide thread-safety, and it appears that this may be something that I can use:</p>
  
  <pre><code>public static void Add(string bar)
  {
      if (!foo.ContainsKey(bar))
          foo.Add(bar, 0);
  
      Interlocked.Increment(ref foo[bar]);
  }
  
  
  public static void Remove(string bar)
  {
      if (foo.ContainsKey(bar))
      {
          if (foo[bar] &gt; 0)
              Interlocked.Decrement(ref foo[bar]);
      }
  }
  </code></pre>
  
  <p>However, my gut instinct is that this won't solve issues when I'm actually adding new items to the Dictionary, so lock immediately comes to mind:</p>
  
  <pre><code>private static Dictionary&lt;string, int&gt; foo = new Dictionary&lt;string, int&gt;();
  private static object myLock = new object();
  
  public static void Add(string bar)
  {
      lock(myLock)
      {
          if (!foo.ContainsKey(bar))
              foo.Add(bar, 0);
  
          Interlocked.Increment(ref foo[bar]);
      }
  }
  
  
  public static void Remove(string bar)
  {
      lock(myLock)
      {
          if (foo.ContainsKey(bar))
          {
              if (foo[bar] &gt; 0)
                  Interlocked.Decrement(ref foo[bar]);
          }
      }
  }
  </code></pre>
  
  <p>Is this approach ideal, or even correct?  Can it be improved?  Am I way off?</p>