title: Alternative to ConcurrentDictionary for portable class library
body: <p>I'm writing a portable class library that targets .NET 4.5, Windows Store apps and Windows Phone 8. I need an efficient in-memory cache mechanism, so I was thinking about using <code>ConcurrentDictionary&lt;K,V&gt;</code>, but it's not available in WP8.</p>
  
  <p>There will be many reads and relatively few writes, so ideally I'd like a collection that supports lock-free reads from multiple threads, and write by a single thread. The non-generic <code>Hashtable</code> has that property, <a href="http://msdn.microsoft.com/en-us/library/system.collections.hashtable.aspx">according to MSDN</a>, but unfortunately it's not available in the PCL...</p>
  
  <p>Is there another collection class available in the PCL that matches this requirement? If not, what would be a good way to achieve thread safety without locking for reads? (locking for writes is OK, since it won't happen too often)</p>
  
  <hr>
  
  <p>EDIT: thanks to JaredPar's guidance, I eventually implemented my cache in a completely lock-free fashion, using <code>ImmutableDictionary&lt;TKey, TValue&gt;</code> from <a href="https://www.nuget.org/packages/Microsoft.Bcl.Immutable">Microsoft.Bcl.Immutable</a>:</p>
  
  <pre><code>class Cache&lt;TKey, TValue&gt;
  {
      private IImmutableDictionary&lt;TKey, TValue&gt; _cache = ImmutableDictionary.Create&lt;TKey, TValue&gt;();
  
      public TValue GetOrAdd(TKey key, [NotNull] Func&lt;TKey, TValue&gt; valueFactory)
      {
          valueFactory.CheckArgumentNull("valueFactory");
  
          TValue newValue = default(TValue);
          bool newValueCreated = false;
          while (true)
          {
              var oldCache = _cache;
              TValue value;
              if (oldCache.TryGetValue(key, out value))
                  return value;
  
              // Value not found; create it if necessary
              if (!newValueCreated)
              {
                  newValue = valueFactory(key);
                  newValueCreated = true;
              }
  
              // Add the new value to the cache
              var newCache = oldCache.Add(key, newValue);
              if (Interlocked.CompareExchange(ref _cache, newCache, oldCache) == oldCache)
              {
                  // Cache successfully written
                  return newValue;
              }
  
              // Failed to write the new cache because another thread
              // already changed it; try again.
          }
      }
  
      public void Clear()
      {
          _cache = _cache.Clear();
      }
  }
  </code></pre>