From a355313e020684c98969d07ae87c3f9bca6516df Mon Sep 17 00:00:00 2001 From: Russell Gray Date: Wed, 4 Feb 2015 15:18:30 +0000 Subject: [PATCH] Call TryGetValue in overload of ConcurrentDictionary.GetOrAdd to avoid acquiring lock. There are two overloads of ConcurrentDictionary.GetOrAdd. One accepts a factory method to generate the value if the key is not found, and calls TryGetValue for the existence check which is a lock-free operation. The other overload, however, does not call TryGetValue - it simply calls straight through to TryAddInternal, which will obtain a bucket lock *before it does the existence check*. This violates the documented claim of ConcurrentDictionary of lock-free reads. This commit simply adds the same TryGetValue check, making the two overloads consistent. --- .../src/System/Collections/Concurrent/ConcurrentDictionary.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/mscorlib/src/System/Collections/Concurrent/ConcurrentDictionary.cs b/src/mscorlib/src/System/Collections/Concurrent/ConcurrentDictionary.cs index ef18182c0cf6..ee66cb289399 100644 --- a/src/mscorlib/src/System/Collections/Concurrent/ConcurrentDictionary.cs +++ b/src/mscorlib/src/System/Collections/Concurrent/ConcurrentDictionary.cs @@ -1064,6 +1064,10 @@ public TValue GetOrAdd(TKey key, TValue value) if (key == null) throw new ArgumentNullException("key"); TValue resultingValue; + if (TryGetValue(key, out resultingValue)) + { + return resultingValue; + } TryAddInternal(key, value, false, true, out resultingValue); return resultingValue; }