views:

95

answers:

4

Hi,

I just came across the question - is the access of an object safely possible across threads in C#.

E.g. with the code

//Somewhere long ago
MyClass myVar = new MyClass("First Instance");

//Then later, happening at the same time
//In thread one
myVar = new MyClass("Second Instance");

//In thread two
myVar.PrintName();

I don't care whether the first or the second instance is used, but is it possible that myVar is at some point not valid at all (e.g. pointing to a non existing location, because maybe the object reference is only partly updated before used in the other thread)


Side question about locks:

If I leave a lock - are then all outstanding writes committed to memory?

My question here is if I reference a variable in a lock, I know only one thread can access the lock at the same time - but can it happen that I write to the variable in one thread (and the write is only done to the cache), and after that in the other thread even inside the lock getting the old value of the variable (because the cache is not committed or I still have an old value in the cache of this thread)?

A: 

The code example in your question is thread-safe. Obviously depending on what you do inside that constructor, but "in general" the myVar ref will be valid (in general cause there are some low level things you could do, like the FormatterServices, etc). A new object will be created by using the constructor, and will be returned to the correct thread automatically. To me it is one of the best ways to makes sure that code is thread safe, by creating new objects on every thread.

Raymond Roestenburg
+1  A: 

To your first. Its almost certainly safe but I would lock it none the less.

As to your cache question what cache are you talking about, the only ones I can think of are the CPU caches, if we had worry about whether these we're dirty and needed flushing we'd all be in a lot of trouble.

Edit: From your comment I see that the CPU cache is what you are refering to.

Mutli-core and Multi-processor hardware ensures that any data in a cache that is out-of-date will not be used.

AnthonyWJones
Yes i meant the CPU caches - so the code inside lock areas are ensured to be "cache clean"?
Fionn
All code is "cache clean" its just not something we have to worry about, its a hardware problem ;). There are no situations where thread-safe coding may still need further work to make "cache clean". OTH thread-unsafe code is unsafe even with single processor/cache.
AnthonyWJones
A: 

I would say that as long as you're not explicitly dereferencing the objects, there's no threat of there being a null reference. The only time might be if you start thread two prior to initializing myVar. I don't think you need a lock in this simple example. As for your side question, to which cache are you referring?

ankushnarula
+1  A: 

I know your question is about .NET and I can't tell you the answer there. However, in Java, this code would definitely NOT be safe.

The risk is that code reordering (an optimisation step) would see the object reference being updated BEFORE the constructor had completed running - hence the second thread could see a partially constructed version of the second object.

In java, you could fix this by making the object reference volatile, or protecting it behind some kind of AtomicReference (or through synchronization, of course) - any of which impose a "memory barrier" that limits the optimization that can be done in order to ensure that a partially constructed object is never visible.

As I say, I don't know enough about the .NET memory model to know whether .NET will have the same issue.

Bill Michell