Thread-safe Dictionary

T

tamara.roberson

I am porting some code to use generics. Currently, we have a
synchronized Hashtable called as follows:

private Hashtable table = Hashtable.Synchronized (new Hashtable ());

What I would like to do is to port this to a Dictionary so that it can
be type-safe:

private Dictionary<string,string> table = new Dictionary<string,string>
();

But this loses our synchronization. I was suprised to find that there
is no built-in method for an automatically synchronized Dictionary. So
what should I do?

Some options:

* add 'volatile' keyword to declaration
* wrap all modifications of the table with lock(table) { ... }
* use some other locking mechanism
* stick to using Hashtable for now, threading hurts my my head and its
better to just leave it alone and not break the whole thing :)

Thanks!
Tamara
 
N

Nicholas Paldino [.NET/C# MVP]

Tamara,

The first option, adding the volatile keyword to the declaration will do
nothing for actually making the operations on the dictionary thread-safe.
It will only affect accessing the reference.

Your best option is to not touch anything. The performance of the
hashtable compared to the Dictionary<string, string> isn't going to be that
far off (not counting synchronization), since you are using reference types
for the key and the value, there is no boxing, and less of a performance
hit.

If you insist on using a Dictionary<string, string>, then I would create
an implementation of IDictionary<TKey, TValue> which synchronizes calls made
to it internally.

Hope this helps.
 
W

William Stacey [MVP]

Here is a synced version below. I have to admit I did not test this fully.
Nor am I totally convinced that some of these methods really don't need a
lock (i.e. ContainsKey, Count, etc) - but I used SyncHashTable as a guide
there. To be totally sure, you could add the lock.

public class SafeDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
private readonly object syncRoot = new object();
private Dictionary<TKey, TValue> d = new Dictionary<TKey, TValue>();

#region IDictionary<TKey,TValue> Members

public void Add(TKey key, TValue value)
{
lock (syncRoot)
{
d.Add(key, value);
}
}

public bool ContainsKey(TKey key)
{
return d.ContainsKey(key);
}

public ICollection<TKey> Keys
{
get
{
lock (syncRoot)
{
return d.Keys;
}
}
}

public bool Remove(TKey key)
{
lock (syncRoot)
{
return d.Remove(key);
}
}

public bool TryGetValue(TKey key, out TValue value)
{
lock (syncRoot)
{
return d.TryGetValue(key, out value);
}
}

public ICollection<TValue> Values
{
get
{
lock (syncRoot)
{
return d.Values;
}
}
}

public TValue this[TKey key]
{
get
{
return d[key];
}
set
{
lock (syncRoot)
{
d[key] = value;
}
}
}

#endregion

#region ICollection<KeyValuePair<TKey,TValue>> Members

public void Add(KeyValuePair<TKey, TValue> item)
{
lock (syncRoot)
{
((ICollection<KeyValuePair<TKey, TValue>>)d).Add(item);
}
}

public void Clear()
{
lock (syncRoot)
{
d.Clear();
}
}

public bool Contains(KeyValuePair<TKey, TValue> item)
{
return ((ICollection<KeyValuePair<TKey,
TValue>>)d).Contains(item);
}

public void CopyTo(KeyValuePair<TKey, TValue>[] array, int
arrayIndex)
{
lock (syncRoot)
{
((ICollection<KeyValuePair<TKey, TValue>>)d).CopyTo(array,
arrayIndex);
}
}

public int Count
{
get
{
return d.Count;
}
}

public bool IsReadOnly
{
get { return false; }
}

public bool Remove(KeyValuePair<TKey, TValue> item)
{
lock (syncRoot)
{
return ((ICollection<KeyValuePair<TKey,
TValue>>)d).Remove(item);
}
}

#endregion

#region IEnumerable<KeyValuePair<TKey,TValue>> Members

public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return ((ICollection<KeyValuePair<TKey,
TValue>>)d).GetEnumerator();
}

#endregion

#region IEnumerable Members

System.Collections.IEnumerator
System.Collections.IEnumerable.GetEnumerator()
{
return ((System.Collections.IEnumerable)d).GetEnumerator();
}

#endregion
}

--
William Stacey [MVP]

|I am porting some code to use generics. Currently, we have a
| synchronized Hashtable called as follows:
|
| private Hashtable table = Hashtable.Synchronized (new Hashtable ());
|
| What I would like to do is to port this to a Dictionary so that it can
| be type-safe:
|
| private Dictionary<string,string> table = new Dictionary<string,string>
| ();
|
| But this loses our synchronization. I was suprised to find that there
| is no built-in method for an automatically synchronized Dictionary. So
| what should I do?
|
| Some options:
|
| * add 'volatile' keyword to declaration
| * wrap all modifications of the table with lock(table) { ... }
| * use some other locking mechanism
| * stick to using Hashtable for now, threading hurts my my head and its
| better to just leave it alone and not break the whole thing :)
|
| Thanks!
| Tamara
|
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top