Earlier we used Collections, they were never thread safe. Generics introduced in .NET 2.0 are TypeSafe
but not ThreadSafe
.
Generics are TypeSafe
means whenever you are going to declare any generic type, you need to specify the type that is going to be held by the List. And whenever you are going to retrieve any item from list, you will get the actual type item, not an Object
like we get from ArrayList
.
But Generics are not ThreadSafe
, it’s a programmer’s responsibility. Means let’s say if you have a list collecting some objects. That list is shared amongst several threads, then it may work hazardously if two threads try to access the List
at the same point of time, like adding/removing/iterating items from the same list at the same time.
Thread safety can be implemented with the help of locking the collection and other similar ways. But locking the entire list for the sake of adding/removing an item could be a big performance hit for an application based on the circumstances.
.NET 4.0 provides new classes for the concurrency as Concurrent collections. These are:
ConcurrentDictionary< Key , Value>
: Thread safe dictionary in key value pairsConcurrentQueue<T>
: Thread safe FIFO data structureConcurrentStack<T>
:Thread safe LIFO data structure ConcurrentBag<T>
: Thread safe implementation of an unordered collectionBlockingCollection<T>
: Provides a Classical Producer Consumer pattern
All the above classes are available in the namespace System.Collections.Concurrent
.
These collections allow us to share the data amongst several threads without any worry.
Concurrent Collections are the key of Parallel programming, that is introduced in .NET 4.0.
So let’s discuss the very commonly used list ConcurrentDictionary
.
- A thread safe add/remove from dictionary.
- Very user friendly methods that make it unnecessary for code to check if a key exists before add/remove.
AddOrUpdate
: Adds a new entry if doesn’t exist else updates existing one GetOrAdd
: Retrieves an item if exists, else first adds it then retrieves it TryAdd
, TryGetValue
,TryUpdate
, TryRemove
: Allows to do the specified operation like Add
/Get
/Update
/Remove
and if it fails, then does the alternative action.
Benefits of the above Concurrent collections:
- Now programmer doesn’t need to take care of thread safety.
- Uses light weight synchronization like
SpinWait
, SpinLock
, etc. that use spinning before putting threads to wait – for short wait periods, spinning is less expensive than wait which involves kernel transition. - Means faster add/remove/iterate in multithreading environment without writing the code for it.
- Some other classes like
ConcurrentQueue
& ConcurrentStack
don’t rely on Interlocked operations instead of locks which make them faster.
There is lot more to discuss on this. But keeping it short and simple, let’s finish. We’ll discuss other things in subsequent posts.