views:

73

answers:

3

(I'm interested in the .NET CLR)

What exactly happens when one thread changes the object a variable references while another thread is executing a method on the original object?

For example, say the type Foo has a variable 'Bar' of the type Bar, and Bar has no class-level state (for now at least, I'd like to keep this scenario simple):

// Thread 1
foo.Bar = new Bar();
foo.Bar.SomeMethod();

In the meantime, before this finishes executing ...

// Thread 2
foo.Bar = new Bar();

What happens to the method that is (was?) executing on Thread 1? Is everything it needs to complete already on the stack?

Does it change things if thread 2 does this instead?

foo.Bar = null;
+1  A: 

-- edit: corrected confusing sentence.

Well, actually assigning to the variable will be atomic, so it's not like the call will suddenly realise 'oh my I'm null!' while executing .SomeMethod()

What can happen, though, is that foo.Bar.SomeMethod() itself will not be called, because Thread 2 will have (maybe) set it to null first; so it just won't execute (it will crash with a null ref exception).

Same applies with your first example; it'll just call .SomeMethod on the new object.

I think you're thinking things may change while .SomeMethod is running, right? No. Nothing will change in there. It will still have the context of itself.

Noon Silk
If thread 2 sets `foo.Bar` to `null` before the method is called, it will not only not execute, it will actually generate a null reference exception. Your explanation sounds to me as if the runtime will just ignore the method call.
Thorarin
Thorarin: Yes, correct. I admit I worded it really badly. I blame bad coffee.
Noon Silk
Variable assignment is not atomic. It consists of (at least) 2 assembler instructions, a load and a store, and the schedule could interrupt your thread right in between those two.
Blindy
Interesting; I'd like someone to confirm that.
Noon Silk
I don't see how the atomicity of that operation is relevant here at all. The actual storing of the new reference *is* atomic, so there is no way there can be an invalid reference at any point in time.
Thorarin
Agreed.
Noon Silk
+3  A: 

If the call is guaranteed to already be inside SomeMethod(), then nothing unusual will happen - this is an implicit argument for methods, so it would never use the value of the field (or property, whichever it is) directly.

Whether you can truly guarantee that is another matter.

Pavel Minaev
And that "this" on the stack is what saves you from being garbage collected in this scenario, should the GC kick in on the Thread 2 foo.Bar = new Bar();
rice
A: 

What exactly happens when one thread changes the object a variable references while another thread is executing a method on the original object?

What happens is that you rewrite your code to properly synchronize access to these fields.

Cheeso