Home > Guides > Programming > .NET and Windows Programming

Toggle Open Guide Table of ContentsGuide Contents

Close Table of ContentsGuide Contents

Close Table of Contents

Collections and Thread Safety

Last updated Jan 1, 2004.

The default behavior of all the collection classes is not generally thread safe. Although any number of threads can read a collection simultaneously, a single thread modifying the collection can cause undefined behavior for any other threads that are accessing it. The Hashtable class guarantees thread safety for a single writer and multiple readers, but if multiple writers are required, the same rules apply as for all the other collection types.

The .NET Framework SDK documentation identifies three primary ways to make collections thread safe:

  • Create a thread-safe wrapper using the Synchronized method, and access the collection exclusively through that wrapper.

  • If the class does not have a Synchronized method, derive from the class and implement a Synchronized method using the SyncRoot property.

  • Use a locking mechanism, such as the lock statement in C# (SyncLock in Visual Basic), on the SyncRoot property when accessing the collection.

lock (SyncLock in Visual Basic) is the easiest and most effective way to guarantee thread safety. Lock is most useful when enumerating a collection. Enumerating through a collection is inherently not thread-safe, and will throw an exception if the collection is modified at any point during the enumeration. To prevent any other thread from modifying the collection, you lock the collection first, like this:

C#

SortedList myCollection = new SortedList();
// code that adds items to the collection
// lock the collection and enumerate it
lock (myCollection.SyncRoot)
{
  foreach (Object item in myCollection)
  {
    // insert your enumeration code here
  }
}

Visual Basic

Dim myCollection as New SortedList()
' code that adds items to the collection
' lock the collection and enumerate it
Dim item as Object
SyncLock myCollection.SyncRoot
  For Each item In myCollection
    ' insert your enumeration code here
  Next item
End SyncLock

As effective as it is, lock isn't very friendly. When a thread acquires a lock in this manner, no other thread can access the collection. You should use lock only when performing an operation that must have exclusive access to the collection, and you should release the lock as soon as possible.

Synchronize is a much friendlier way to allow multiple threads access to a collection. It is a cooperative technique that requires each thread to follow the rules. Fortunately, those rules are very simple: rather than access the shared collection object, each thread obtains a reference to a synchronized collection object and performs all access through that reference. All it takes is a single call to the static Synchronized method, as shown below.

C#

Hashtable myHt = new Hashtable();
// code that adds items to the Hashtable
// obtain a synchronized wrapper around the Hashtable
Hashtable mySyncHt = Hashtable.Synchronize(myHt);
// all access to mySyncHt is synchronized
Console.WriteLine("myHt is {0}" ?
  myHt.IsSynchronized ? "synchronized" : "not synchronized");
Console.WriteLine("mySyncHt is {0}" ?
  mySyncHt.IsSynchronized ? "synchronized" : "not synchronized");

Visual Basic

Dim myHt as New Hashtable()
' code that adds items to the Hashtable
' obtain a synchronized wrapper around the Hashtable
Dim mySyncHt as Hashtable = Hashtable.Synchronize(myHt)
' all access to mySyncHt is synchronized
Dim msg As String
If myHt.IsSynchronized then
  msg = "synchronized"
Else
  msg = "not synchronized"
End If
Console.WriteLine("myHt is {0}", msg)
If mySyncHt.IsSynchronized then
  msg = "synchronized"
Else
  msg = "not synchronized"
End If
Console.WriteLine("mySyncHt is {0}", msg)

The IsSynchronized property returns true if the collection is synchronized.

It's worth repeating that using synchronized lists is cooperative. Nothing prevents a thread from accessing the list through the non-synchronized reference. But if you're careful to code the classes that use the list so all access it through the Synchronized reference, all will be fine.

In practice, you will use a combination of Synchronize and lock to provide thread-safe access to your collections. Most often, you'll use Synchronize during updates to prevent multiple threads from trying to modify the collection at the same time, and lock when you have a longer operation that requires exclusive access.

The other technique for providing thread-safe access involves creating a derived class and implementing your own Synchronize method. That is covered in the next section (next week), when we take a look at creating your own collection classes.

Discussions

Copies of the array?
Posted Dec 23, 2008 03:40 PM by luige21
1 Replies
Hi
Posted Dec 5, 2008 05:10 AM by ajay2000bhushan
2 Replies
You have no clue.
Posted Jun 10, 2008 03:28 PM by theinternetmaster
1 Replies

Make a New Comment

You must log in in order to post a comment.

Related Resources

Jim Mischel"Highly unlikely" does not mean "impossible"
By Jim MischelJuly 18, 2009 No Comments

One of my programs crashed the other day in a very unexpected place.  A call to System.Threading.ConcurrentQueue.TryDequeue (from the Parallel Extensions to .NET) resulted in an OverflowException being thrown.  Investigation revealed a pretty serious bug in the System.Random constructor.

It's Here; Put Away Your Pre-Conceptions on What an OS Must Be: Part II
By John TraenkenschuhMay 24, 2009 No Comments

In the last blog in this series, Traenk relates his first experiences with computers and with coding.  But now, some years have passed. . .

It's Here; Put Away Your Pre-Conceptions on What an OS Must Be: Part I
By John TraenkenschuhMay 24, 2009 No Comments

Traenk relates his past experience with Operating Systems that goes back 25 years, ok, more than that but he ain't tellin'

See More Blogs

Informit Network