-2

I am using a ConcurrentDictionary<string, List<CustomObjects>> in a multi threaded environment.

Multiple threads are accessing the same dictionary for retrieving and modifying the item with unique key only. I mean although there are multiple threads accessing the dictionary each thread is accessing and modifying the element at unique key only.

At any point of time no situation will come that more than one thread are trying to access and modify the element at same key location.

Now my question is even in this case the internal locking happens? Or since the different threads are accessing different element at a time on same dictionary no internal locking or any concurrency mechanism execute?

I believe if more than one thread are trying to modify the element at same key location, by default locks will be executed and concurrency will be ensured. But if the different threads are accessing the different items within the dictionary, will it be done in lock free manner internally?

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
Real Master
  • 347
  • 3
  • 14
  • When you say "concurrent dictionary", do you mean `ConcurrentDictionary`? If so, is the question how this type is implemented internally? I'm pretty sure that beyond the guarantee that parallel updating is safe no actual implementation details are guaranteed, so if the type can manage this guarantee without an explicit lock... **What exactly is your question?** – Lasse V. Karlsen Nov 09 '17 at 12:09
  • 1
    From the [remarks section of the class's documentation](https://msdn.microsoft.com/en-us/library/dd287191(v=vs.110).aspx#Remarks) `For modifications and write operations to the dictionary, ConcurrentDictionary uses fine-grained locking to ensure thread safety. (Read operations on the dictionary are performed in a lock-free manner.) ` – Panagiotis Kanavos Nov 09 '17 at 12:10
  • read the docs........... – The Bearded Llama Nov 09 '17 at 12:11
  • Why are you asking? What is the *actual* problem? Thread-safe doesn't mean a value won't be replaced by another thread right after you finish your update. That's why eg [TryUpdate](https://msdn.microsoft.com/en-us/library/dd287117(v=vs.110).aspx) uses the old value to check for unexpected changes. If it fails, you know the value was modified by someone else – Panagiotis Kanavos Nov 09 '17 at 12:13
  • 2
    `Now my question is even in this case the internal locking happens?` Yes. `I believe if more than one thread are trying to modify the element at same key location, by default locks will be executed and concurrency will be ensured.` Locks don't only get used if more one than thread is used. If a *single* thread is writing it will still use a lock. – mjwills Nov 09 '17 at 12:48

1 Answers1

0

If I understand your question correctly, you have a number of threads, and each thread interacts with an exclusive subset of the ConcurrentDictionary<K,V>. As a minimal example, you have two threads 1 and 2, and a dictionary with two keys "A" and "B". The thread 1 reads and modifies only the key "A", and the thread 2 reads and modifies only the key "B". And you are asking if locking is happening internally in the dictionary.

  1. Reading the value of a key in a ConcurrentDictionary<K,V> is look-free (source code¹).
  2. Updating the value of a key in a ConcurrentDictionary<K,V> requires acquiring a lock (source code).

So locking is happening whenever any thread updates any key. Even if it's a single thread and the dictionary has a single key. But what is more interesting to know, is whether contention happens whenever a thread tries to acquire a lock. Acquiring an uncontended lock is very cheap², but if the lock is already acquired by another thread then the current thread might get blocked, which is costly. During a TryUpdate operation a thread has to acquire a lock and then compare the searched key with existing keys stored in the buckets of the dictionary, and a key comparison can be competitively intensive. For example case-insensitive comparison of extremely long strings. So blocking threads and causing thread-switching is a real concern.

Fortunately the ConcurrentDictionary<K,V> doesn't use the same locker object for all lock operations. It maintains internally a large number of lockers, up to around a thousand, and selects one based on the hashcode of the key. So it's very unlikely that two threads will block each other, contending for the same locker, but it's not mathematically impossible.

¹ .NET 7
² "You can expect to acquire and release a lock in as little as 20 nanoseconds on a 2010-era computer if the lock is uncontended."

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104