Home All Groups Group Topic Archive Search About

Another Thread Safety Question

Author
22 Mar 2007 3:55 PM
Roy
Hypothetical question:

A multi-threaded app has an object with a privately scoped collection (like
ArrayList) that is shared between threads. The model is one thread
creates/reads/writes/updates the collection, and all other threads read the
collection. What are the minimal locks required for thread safety?

Is it safe to only lock access when writing/updating the collection?

Is it overkill to lock access for all access (including shalllow-copy
instance cloning and read-only) in the properties/methods exposed by this
object?

Author
22 Mar 2007 4:57 PM
Peter Duniho
On Thu, 22 Mar 2007 08:55:21 -0700, Roy <R**@discussions.microsoft.com> 
wrote:

> [...] What are the minimal locks required for thread safety?
>
> Is it safe to only lock access when writing/updating the collection?
>
> Is it overkill to lock access for all access (including shalllow-copy
> instance cloning and read-only) in the properties/methods exposed by this
> object?

Well, the question of the least-costly method of locking is a whole other 
level of writing thread-safe code.

That said, consider that if you are writing to the data, you cannot 
reliably read the data until the writing is done.  Thus, locking for 
writing requires that reads are locked too.

You can safely read from multiple threads simultaneously, but you will run 
into the problem that readers still need to lock the data somehow, so that 
the data doesn't get modified during reads.

How best to do this is a subject for a much more detailed discussion, 
probably served better by more in-depth articles or books on the topic.

Pete
Author
22 Mar 2007 5:36 PM
Roy
Thank you Pete. That makes perfect sense to me. In order to convince my
co-workers, what books(s) would you reccommend that I use to prove this
point? Also, I did not see another Microsoft monitored .Net newsgroup dealing
with threading issues... did I miss something?

-Roy
Author
23 Mar 2007 4:28 AM
Peter Duniho
On Thu, 22 Mar 2007 10:36:03 -0700, Roy <R**@discussions.microsoft.com> 
wrote:

> Thank you Pete. That makes perfect sense to me. In order to convince my
> co-workers, what books(s) would you reccommend that I use to prove this
> point? Also, I did not see another Microsoft monitored .Net newsgroup 
> dealing with threading issues... did I miss something?

Sorry, can't help you on either front.  As far as I know, there is not any 
newsgroup specific to threading, though there are Windows programming 
newsgroups that are probably more technical than this one and so might be 
able to offer better advice.  Of course, general threading advice for 
native Win32 threads may or may not apply to .NET threads...I'm not 
exactly an expert on the exact differences between the two with respect to 
how data is managed and stored (though I gather that most of the time, 
there's not any practical difference).

As far as books go, I don't have any idea.  I've never read a book on 
Windows programming, so can't recommend anything specific.  Maybe other 
people will have suggestions.

In any case, I would think it pretty much obvious that since there's no 
automatic mechanism to prevent one thread from writing to memory while 
another thread is reading from the same area, that readers need to lock or 
synchronize with writers.  On a single CPU system, if the data you're 
dealing with is a single processor word, then a read or write operation is 
atomic and you can get away without synchronization, but that's a very 
narrow scenario (and as Jon points out, you still need to make the effort 
to ensure that the two threads are really accessing the same location, by 
marking the variable as volatile).  Other than that, there's simply no 
guarantee of serializing access to data across threads.  I'm not sure you 
should need a book to point this out to others.  :)

Pete
Author
22 Mar 2007 6:05 PM
Jon Skeet [C# MVP]
Peter Duniho <NpOeStPe***@nnowslpianmk.com> wrote:

<snip>

> You can safely read from multiple threads simultaneously, but you will run 
> into the problem that readers still need to lock the data somehow, so that 
> the data doesn't get modified during reads.

While it's not *dangerous* to read from multiple threads, even if
you're reading a single int (which is guaranteed to be changed
atomically) you need to lock, use a memory barrier, or use a volatile
variable to make sure that the read actually sees the most recent
value, rather than a potentially previously read one.

See http://pobox.com/~skeet/csharp/threads/volatility.shtml

(Unfortunately there are various ways in which the .NET memory model is
very poorly specified, but such is life.)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Author
23 Mar 2007 2:06 PM
Fredrik Johansson
Don't reinvent the wheel... Use the static member 'Synchronized' to get a
thread-safe collection instance. For instance:
Queue myQueue = Queue.Synchronized(new Queue());



Regards,
Fredrik

Show quote
"Jon Skeet [C# MVP]" wrote:

> Peter Duniho <NpOeStPe***@nnowslpianmk.com> wrote:
>
> <snip>
>
> > You can safely read from multiple threads simultaneously, but you will run 
> > into the problem that readers still need to lock the data somehow, so that 
> > the data doesn't get modified during reads.
>
> While it's not *dangerous* to read from multiple threads, even if
> you're reading a single int (which is guaranteed to be changed
> atomically) you need to lock, use a memory barrier, or use a volatile
> variable to make sure that the read actually sees the most recent
> value, rather than a potentially previously read one.
>
> See http://pobox.com/~skeet/csharp/threads/volatility.shtml
>
> (Unfortunately there are various ways in which the .NET memory model is
> very poorly specified, but such is life.)
>
> --
> Jon Skeet - <sk***@pobox.com>
> http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
> If replying to the group, please do not mail me too
>
Author
23 Mar 2007 4:50 PM
Jon Skeet [C# MVP]
On Mar 23, 2:06 pm, Fredrik Johansson
<FredrikJohans***@discussions.microsoft.com> wrote:
> Don't reinvent the wheel... Use the static member 'Synchronized' to get a
> thread-safe collection instance. For instance:
> Queue myQueue = Queue.Synchronized(new Queue());

That's fine for single reads/writes, but is no good if a thread does
something like iterating over the collection - at that point, a lock
needs to be obtained for the whole iteration process, to prevent the
collection being modified while iterating.

Personally I dislike the Synchronized method precisely because it sort
of implies that using a "synchronized" version means you can ignore
all threading issues. It doesn't - it just means you need to worry
about the subtle ones instead of subtle and obvious ones...

Jon
Author
24 Mar 2007 2:38 AM
bazad
Last time I had to synchronize access to a collection I simply used locked
on its SyncRoot.

Show quote
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:1174668630.800666.319480@d57g2000hsg.googlegroups.com...
> On Mar 23, 2:06 pm, Fredrik Johansson
> <FredrikJohans***@discussions.microsoft.com> wrote:
>> Don't reinvent the wheel... Use the static member 'Synchronized' to get a
>> thread-safe collection instance. For instance:
>> Queue myQueue = Queue.Synchronized(new Queue());
>
> That's fine for single reads/writes, but is no good if a thread does
> something like iterating over the collection - at that point, a lock
> needs to be obtained for the whole iteration process, to prevent the
> collection being modified while iterating.
>
> Personally I dislike the Synchronized method precisely because it sort
> of implies that using a "synchronized" version means you can ignore
> all threading issues. It doesn't - it just means you need to worry
> about the subtle ones instead of subtle and obvious ones...
>
> Jon
>
Author
24 Mar 2007 8:01 AM
Jon Skeet [C# MVP]
<"bazad" <no reply>> wrote:
> Last time I had to synchronize access to a collection I simply used locked
> on its SyncRoot.

Yes - doing that consistently is better, IMO, than using Synchronized
and then working out where you *also* need locking.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

AddThis Social Bookmark Button