Note that there are some explanatory texts on larger screens.

plurals
  1. POFor .NET 3.5 how would you make a thread-safe get or add cache?
    text
    copied!<p>I have starting working with some .NET 3.5 code and found the following extension method being used for a cache:: </p> <pre><code>public static TValue GetOrAdd&lt;TKey, TValue&gt;(this Dictionary&lt;TKey, TValue&gt; @this, TKey key,Func&lt;TKey,TValue&gt; factory,bool useLocking) { TValue value; if(!@this.TryGetValue(key,out value)) { if (useLocking) { lock ((@this as ICollection).SyncRoot) { if (!@this.TryGetValue(key, out value)) { @this[key] = value = factory(key); } } } else { @this[key] = value = factory(key); } } return value; } </code></pre> <p>The cache in question is keyed by string keys, and with useLocking = true. It is always being accessed by this method (there is no stray <code>TryGetValue</code>). There is also no issue in using the <code>SyncRoot</code> property because the dictionary is private and no where else is it being used. The double locking is dangerous because a dictionary does not support reading while it's being written to. While technically there has been no issue reported yet as the product hasn't shipped, I feel that this approach is going to lead to race conditions.</p> <ol> <li><p>Switch the <code>Dictionary&lt;,&gt;</code> to a <code>Hashtable</code>. We'll lose type-safety but we'll be able to support the concurrency model we're after, (1 writer, multiple readers).</p></li> <li><p>Remove the outer TryGetValue. That way every read, requires acquiring a lock. This is potentially bad for performance, but acquiring an uncontested lock should be fairly cheap.</p></li> </ol> <p>Both are pretty crappy. Does anyone have a better suggestion? If this was .NET 4 code I'd just switch it to a <code>ConcurrentDictionary</code>, but I don't have that option.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload