The Artima Developer Community
Sponsored Link

.NET Buzz Forum
Synchronized .NET Collection Classes are NOT Thread Safe.

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Marcus Mac Innes

Posts: 90
Nickname: macinnesm
Registered: Mar, 2004

Marcus Mac Innes is solutions architect and director of Style Design Systems Ltd
Synchronized .NET Collection Classes are NOT Thread Safe. Posted: Sep 23, 2004 1:25 AM
Reply to this message Reply

This post originated from an RSS feed registered with .NET Buzz by Marcus Mac Innes.
Original Post: Synchronized .NET Collection Classes are NOT Thread Safe.
Feed Title: Marcus Mac Innes' Blog
Feed URL: http://www.styledesign.biz/weblogs/macinnesm/Rss.aspx
Feed Description: Issues relating to .NET, Service Oriented Architecture, SQL Server and other technologies.
Latest .NET Buzz Posts
Latest .NET Buzz Posts by Marcus Mac Innes
Latest Posts From Marcus Mac Innes' Blog

Advertisement

Call me a purist, but when someone asks me whether something is thread safe, I like to re-phrase the question in my head to something like "Is this air traffic control system thread safe" before answering...Yes or No?

So you can imagine my surprise then after finally tracking down a threading issue only to discover that the bug was in fact caused by the .NET synchronized Hashtable and it turns out that the synchronized Hashtable is in fact not thread safe, but thread safe "ish" and to me that's NOT thread safe at all.

The documentation for Hashtable and other collection objects which implement System.Collections.ICollection indicates that the static method Synchronized "Returns a synchronized (thread-safe) wrapper for the Hashtable.". Creating one coundn't be simpler, a small change in the Hashtable's initialisation provides you with thread safety...

Hashtable threadSafeHashtable = Hashtable.Synchronized(new Hashtable());

The Hashtable class contains a private class called SyncHashtable which simply subclasses Hashtable and overrides its properties and methods. In reality, these wrappers synchronize data access by simply wrapping access in a lock statement. Here is the Hashtable's synchronized Add method:

public override void Add(object key, object value)
{
      lock (this._table.SyncRoot)
      {
            this._table.Add(key, value);
      }
}

Perfect right?

Well not exactly... You see the Add method above is thread safe. Only one thread can add to the Hashtable at a time. But if we look a little closer, we find that not all properties and methods provide lock safety. Here is the implementation of the indexer which you will notice is missing a lock on the "get":

public override object this[object key]
{
      get
      {
            return this._table[key];
      }
      set
      {
            lock (this._table.SyncRoot)
            {
                  this._table[key] = value;
            }
      }
}

This is a typical example of naive thread safety. The assumption goes that mutliple threads can simultaneously read from an object safely, but only one thread at a time can write to the object safely. And this is the implementation we see in System.Collection.Hashtable (above).

This design works perfectly well and provides optimum performance since we are not holding up threads who only wish to read an objects data, they simply work away oblivious to each other, only when a thread wishes to write does it need to synchronize its access to the data. There is however one HUGE assumption in this design, the writes must be "atomic".

In some cases writes to memory locations are actually atomic. For instance setting a value of a bool or int on 32bit single processor machine in .NET 1.1 just happens to be atomic. We run into problems on multi processor machines however due to processor level memory caching and often need to qualify writes with System.Threading.Thread.MemoryBarrier() (discussed here) which flushes the processor's memory cache. But now we have 2 separate statements which together are definitely not atomic.

So why is this important when looking at the synchronization design of the System.Collections.Hashtable.SyncHashtable class?

Well if a thread always has the green light to perform a read, then it makes the assumption that the data to be read exists in a fully written state. If it were allowed to read "while" another thread was in the middle of write (albeit one thread writing at a time), then the data could be half written when the read is performed and hence we have a subtle and often difficult to locate threading bug.

Other methods on SyncHashtable that fall foul of the design flaw include: Contains, ContainsKey, ContainsValue, CopyTo, GetEnumerator, GetHash and KeyEquals.

Don't get caught out!

[Update:] As of .NET v2.0.40607 SyncHashtable.CopyTo has been upgraded to include a lock.

Read: Synchronized .NET Collection Classes are NOT Thread Safe.

Topic: Windows XP SP2 Slowdown? Previous Topic   Next Topic Topic: I need to slap a toshiba engineer

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use