ose
ose

Reputation: 4075

Can a constructor be pre-empted?

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?

Upvotes: 10

Views: 328

Answers (2)

user743382
user743382

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

Narendra Pathai
Narendra Pathai

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.

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.

Upvotes: 4

Related Questions