|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Another Thread Safety QuestionHypothetical 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? On Thu, 22 Mar 2007 08:55:21 -0700, Roy <R**@discussions.microsoft.com>
wrote: > [...] What are the minimal locks required for thread safety? Well, the question of the least-costly method of locking is a whole other > > 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? 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 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 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 Sorry, can't help you on either front. As far as I know, there is not any > 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? 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 Peter Duniho <NpOeStPe***@nnowslpianmk.com> wrote:
<snip> > You can safely read from multiple threads simultaneously, but you will run While it's not *dangerous* to read from multiple threads, even if > into the problem that readers still need to lock the data somehow, so that > the data doesn't get modified during reads. 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 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 > 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 That's fine for single reads/writes, but is no good if a thread does> thread-safe collection instance. For instance: > Queue myQueue = Queue.Synchronized(new Queue()); 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 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 > <"bazad" <no reply>> wrote: Yes - doing that consistently is better, IMO, than using Synchronized > Last time I had to synchronize access to a collection I simply used locked > on its SyncRoot. 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 |
|||||||||||||||||||||||