I have implemented a simple cache using the dictionary class:
private Dictionary<int, byte[]> cache = new Dictionary<int, byte>();
public void SetPicture(int id, byte[] bytes)
{
cache[id] = bytes;
}
public byte[] GetPicture(int id)
{
if (cache.Contains(id)) {
return cache[id];
}
return null;
}
SetPicture is only called from a single background thread. (This background thread is updating user profile pictures from an active directory query).
GetPicture is called from multiple other threads (threads handling http requests).
Items will never be removed from the cache.
So is this code thread safe? Or do I need to block access to the internal Dictionary while writing to it in SetPicture?
No it is not safe; all access to a dictionary needs to be synchronized, as the contents of a
Dictionary<,>are not guaranteed for readers against a writer. Also, a separate contains/get check is an obvious thread-race.Options:
Hashtable– that supports one writer and multiple concurrent readers without synchronization (downside here is that your key,int, is a value-type, so will need to be boxed;Hashtableis more inviting when using a reference-type key, such asstring)ConcurrentDictionary<,>ReaderWriterLockSlimto synchronize (assuming reads are much more common than writes)lockto synchronize (assuming non-trivial writes)However! If you use the
Hashtableapproach do not do a separateContains/ get – just use the indexer. If you getnullit wasn’t there. Otherwise you have a race condition.