title: Is a Dictionary<K,V> thread safe for simulataneous reading and additions?
body: <p>This question relates to a very specific and common scenario in which a dictionary is being used for on-demand caching of items in a multi-threaded environment. To avoid thread locking it's preferable to test for an existing cache item outside of a sync lock, but if we subsequently have to add an item then that counts as a write to the dictionary and therefore most advice I've been reading on stackoverflow is that you need to lock on the read as well as the write because the dictionary's internal state might be being altered by the calls to add().</p>
  
  <p>However, looking through Microsoft's AjaxControlToolkit (scriptObjectBuilder class) the code does in fact perform TryGet() outside of any locks and only locks to Add() new items to the dictionary. I can see how this might be possible if the bucket that an item is placed into never changes once added, but my suspicion is that this is wrong and might be a source of bugs.</p>
  
  <p>Thanks.</p>
  
  <p><strong>UPDATE</strong>
  Going by the .Net documentation I think that the described pattern is indeed wrong. However I was wondering if the particular implementation of Dictionary allows it and that the AjaxControlToolkit was relying on this (which would be dubious). On examining the code in Reflector I'm pretty sure that this is indeed wrong, the Dictionary.Resize() method reallocates the number of buckets and moves bucket items around, so any thread in the middle of a TryGet() could potentially be working on unstable data.</p>
  
  <p><strong>UPDATE</strong>
  A defect was already logged against the AjaxControlToolkit on codeplex. See:</p>
  
  <ul>
  <li><a href="http://ajaxcontroltoolkit.codeplex.com/WorkItem/View.aspx?WorkItemId=9956" rel="nofollow noreferrer">Possible Thread Safety bug in ScriptObjectBuilder</a> </li>
  <li><a href="http://forums.asp.net/p/1523334/3667331.aspx#3667331" rel="nofollow noreferrer">Thread safety issue in ScriptObjectBuilder.</a></li>
  </ul>