views:

609

answers:

3

Consider code that involves multiple threads writing to a shared data structure. Now each of these threads write objects to the shared container that are essentially unique. Take the following (fictitious) example:

class Logger
{
   IDictionary<string, Log> logDictionary = new Dictionary<string, Log>();

   // Method called by several other threads
   void AddLog(Log log)
   {
      logDictionary[log.ID] = log;
   }

   // Method called by a separate thread
   IList GetLog(/*some criteria*/)
   {
      // loop through logDictionary and
      // create an IList based on criteria
   }
}

I understand clearly that concurrent access to a shared object can be a problem if multiple threads try to update the same 'variable' (or slot) leading to race conditions. Now my question has 3 parts.

(1) Is synchronization necessary if the threads are making blind updates? (Even if they are updating the same slot/variable)?

(2) Is it thread-safe to assume, given that each thread is writing a unique object, there is no need to synchronize access to the shared dictionary/container?

(3) Does the call to GetLog() by another thread, really pose problems even if the dictionary is being updated simultaneously by other threads?

+3  A: 

The biggest problem would be if any of the threads added/removed a key in the dictionary. This could cause significant re-building internally (quite possibly breaking any competing reads and writes that are in progress), so yes; you do need to synchronize access. You might be OK if all the threads are reading/writing against existing keys, but I don't think it would be guaranteed.

I don't know about java, but in C# there is ReaderWriterLockSlim which may (if you absolutely need it) allow multiple concurrent readers or one writer (not both) - but it is often simpler (and sometimes even quicker) just to go mutex (via lock etc).

edit

Also - for strongly-typed dictionary types (i.e. generics etc), with value-types that are over-sized, the update won't be interlocked; another thread could in theory see an in-progress update of such a value. For example, a guid on x86, etc.

Marc Gravell
+1  A: 

1) What do you mean by "blind update"?

2) No. Assuming that Dicitonary is implemented with a hash table, you need to synchronize access in order to handle hash collisions, increasing the size of the table etc. You might be able to get away with locking individual elements in the table rather than a shared lock for the entire data structure in some cases, but that has overhead as well.

3) Depends if the updating is atomic or not.

janneb
A blind update is when update a variable without reading it first, because the previous value held by the variable has no significance
Mystic
if something is written, then at some point, it will be read - even if its not by the thing doing the writing (otherwise, why write it at all if its only going to be discarded?). The problem, if you dont sync, is that the read could be wrong down the track.
Chii
+3  A: 

The container classes in C# are not thread-safe for writing, which means that you MUST make sure that only one thread accesses a container class instance at the same time, even if each thread writes to a different key in the dictionary.

For reading, Dictionary is thread safe, i.e. you can read from the dictionary from multiple threads at the same time. It is not safe to read and write at the same time, though.

Details here.

Mark Probst