Reputation: 4075
Is it possible for a constructor to be pre-empted in C#?
For example, consider the code:
public class A
{
public bool ready = true;
public A()
{
ready = false; // Point #1
// Other initialization stuff
ready = true; // Point #2
}
}
Somewhere else in the code two threads have access to a variable of type A, the first thread calls the constructor which is pre-empted at point #1. Then the second thread tests for ready
and finds it to still be true therefore it does something bad.
Is this scenario possible?
More specifically:
lock
in the constructor?Upvotes: 10
Views: 328
Reputation:
I don't think the accepted answer is correct. Igor Ostrovsky's "The C# Memory Model in Theory and Practice" (part 2 here) explains the issues thoroughly, and one of the examples illustrates exactly what you're asking about.
It gives the code
class BoxedInt2
{
public readonly int _value = 42;
void PrintValue()
{
Console.WriteLine(_value);
}
}
class Tester
{
BoxedInt2 _box = null;
public void Set() {
_box = new BoxedInt2();
}
public void Print() {
var b = _box;
if (b != null) b.PrintValue();
}
}
and notes:
Because the BoxedInt instance was incorrectly published (through a non-volatile field, _box), the thread that calls Print may observe a partially constructed object! Again, making the _box field volatile would fix the issue.
I strongly encourage reading the entire article, it's a very useful read.
Upvotes: 5
Reputation: 41935
Is the object being constructed only assigned to the shared variable after the constructor exits, thereby avoiding the question altogether?
Yes. When you construct the object only when the constructor returns then value of the reference is assigned to variable. So only after that the other thread will be able to call to check if value is true
or false
.
Two threads cannot enter a constructor at the same time ever.
But you can easily do a mistake if you are publishing present reference to some share list. Take care of not to do something like this in your constructor
A(List sharedList){
sharedList.add(this);
//initializing instance variables
}
Pardon for Java code. So in this case you are publishing incomplete created object to a shared list which can be accessed by other thread and can lead to many issues.
Don't publish the "this" reference during construction, Java. Don't know surely if same applies for C#
Then that brings me back to the original question, in C# can the constructor be pre-empted?
As far as preemption is concerned Yes IMO a thread can be interrupted while constructor is running. Constructor is just like a normal method but with special semantics.
That does not at all affect the thread safety of code as only a single thread can be inside an object's constructor. So it is totally thread safe, until you don't escape incompletely built this
reference.
If so, does this mean that there should be synchronization code such as lock in the constructor?
No only a single thread can be inside a constructor so it is inherantly thread-safe.
Upvotes: 4