Correct way to lock the dictionary object Correct way to lock the dictionary object multithreading multithreading

Correct way to lock the dictionary object


With Dictionary<,> you have to lock both reading and writing. So both

lock( ConnectionList ) {   ConnectionList.Add( key, res );}

and

lock( ConnectionList ) {   res = ConnectionList[ key ];}

and

lock( ConnectionList ) {   int cnt = ConnectionList.Count;}

and

lock( ConnectionList ) {   ConnectionList.Clear();}

and

lock( ConnectionList ) {   foreach ( var kv in ConnectionList ) {      // Do things   }}

and so on :-)

With ConcurrentDictionary<,> you don't need any locking, but note that the syntax is a little different than the one of the Dictionary<,>


So can anybody please suggest me which is the best way to lock the dictionary?

if you want to continue using the classic Dictionary<,> AFAK you have to look to ICollection interface implemented by Dictionary and use the property ICollection.SyncRoot which by definition

MSDNGets an object that can be used to synchronize access to the ICollection. So to achieve this you can do something like this

If I use ConcurrentDictionary do I still need to use lock on it or will it handle everything by itself.

From MSDN
ConcurrentDictionary is designed for multithreaded scenarios. You do not have to use locks in your code to add or remove items from the collection. However, it is always possible for one thread to retrieve a value, and another thread to immediately update the collection by giving the same key a new value.

If I have to use lock on ConcurrentDictionary, I have to use lock on it directly or again I have to lock the SyncRoot object for it

Yes you have to use lock on SyncRoot if you want to do Atomic methods execution when you use GetOrAdd or AddOrUpdate methods


  1. So can anybody please suggest me which is the best way to lock the dictionary

You can use it's SyncRoot or create a private object that you lock when accessing the dictionary object, e.g.

private static object _sybcRoot = new object();public static void Add( string key, string res)    lock( _sybcRoot ) {       ConnectionList.Add( key, res );    }}

You have to use the same lock object to guard the access to the same resource. Otherwise threads may "think" the resource is free, whereas in reality it is used by the other thread which just happen to lock it on the other object's sync root.

  1. If I use ConcurrentDictionary do I still need to use lock on it or will it handle everything by itself.

No, there is no need for locking when using any Concurrent* collection. It is thread-safe by design, but this syntax is slightly different. Concurrent* collections use lockless approach, which is better in a situations when you don't have many threads competing for access (optimistic concurrency)

  1. If I have to use lock on ConcurrentDictionary, I have to use lock on it directly or again I have to lock the SyncRoot object for it