10

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:

  1. Can a constructor be pre-empted?
  2. If so, does this mean that there should be synchronization code such as lock in the constructor?
  3. Is the object being constructed only assigned to the shared variable after the constructor exits, thereby avoiding the question altogether?
ose
  • 4,065
  • 2
  • 24
  • 40
  • 8
    Number 3 is correct. In no way more than one thread can enter the constructor code for a single object. – Mohammad Dehghan Sep 14 '13 at 11:37
  • The question seems wrong. If you have an object of A, you cannot do objOfA.A().... Constructor is only called when object is created using the new keyword. Once object is created, there is no way constructor can be explicitly called on a created object. – fahadash Sep 14 '13 at 11:40
  • 1
    The constructor of an object cannot ever be entered into by more than one thread (obviously all objects are constructed only once). – Jon Sep 14 '13 at 11:41
  • @Jon C# and the publicly available .NET Framework classes don't allow an object to have its constructor called more than once (even though it's possible from IL), but they do allow objects that don't have their constructor called at all. –  Sep 14 '13 at 11:43
  • The OS can preempt any user-mode code at any time. It does not know what a constructor is, neither does it know what .NET is. – usr Sep 14 '13 at 12:59
  • You may find my [answer here](http://stackoverflow.com/a/10281524/158779) interesting. And [this question](http://stackoverflow.com/q/8358707/158779) is also relevant. – Brian Gideon Sep 15 '13 at 01:30

2 Answers2

5

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.

  • +1: You are absolutely right. The accepted answer is not technically correct. An object instance **can** be assigned to the variable **before** the constructor is even executed! I explain how this can happen in my answer [here](http://stackoverflow.com/a/10281524/158779) as well. – Brian Gideon Sep 15 '13 at 01:26
  • I dont know much about C# but how can Left hand value be assigned before the right hand function (constructor) is completed executing? And using volatile does not relate to what you are discussing. Volatile atleast in java provides visibility and not atomicity. Are you clear about that? – Narendra Pathai Sep 20 '13 at 09:24
  • @NarendraPathai In a single thread, that's impossible, you won't ever see that. However, without `volatile` or other synchronisation, the runtime may optimise without regard to other threads. `_box = new BoxedInt2();` can become (pseudo-code) `var tmp = newuninit BoxedInt2; tmp._value = 42; _box = tmp;`, and after that, since a single thread cannot see any difference if `tmp._value = 42; _box = tmp;` get reordered, they are allowed to be reordered. That reordering may make sense if (fe) this allows multiple different assignments to `_box` to be combined to store only the last value. –  Sep 20 '13 at 09:31
  • @JonSkeet I hope Jon can give and explanation to that. I still have doubts. – Narendra Pathai Sep 20 '13 at 11:45
4

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.

Safe publication issues - publishing incompletely created object

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.

Narendra Pathai
  • 41,187
  • 18
  • 82
  • 120
  • Two threads cannot enter the constructor of the same object *ever*. And on different objects you simply don't care (unless `static` members come into play). – Jon Sep 14 '13 at 11:41
  • @Jon Yupp added that punch character _ever_. Thanks. – Narendra Pathai Sep 14 '13 at 11:43
  • So what would happen if hypothetically I did add "this" to the shared list? A) is that possible in C#? B) Would it then be possible for two threads to access the object while the constructor was still running? – ose Sep 14 '13 at 11:45
  • @ose Yes in that case as you are publishing present object to a shared list, other thread can see an incompletely created object. – Narendra Pathai Sep 14 '13 at 11:46
  • @ose yes you can use `this` and add that to a list in c# AFAIK. – Narendra Pathai Sep 14 '13 at 11:47
  • Then that brings me back to the original question, in C# can the constructor be pre-empted? – ose Sep 14 '13 at 11:51
  • @ose I have added the link of article that discusses this issue for Java. Read that and see if the same is possible for c# – Narendra Pathai Sep 14 '13 at 11:51
  • And if you need to put `this` of a created object somewhere where it is shared, I think the correct way is to use a factory method, which creates the object, *then* shares it. Usually this in this case a private constructor is used, to force use of the factory method. Note, talking from Java background, not 100% sure if this applies to C#. – hyde Sep 14 '13 at 11:52
  • @ose Read the explanation to your comment that I have provided. – Narendra Pathai Sep 14 '13 at 11:54