none
Are constructor local variables thread safe?

    Question

  • If a constructor method declares local variables then is access to these variables thread safe?

    Thanks,

    cats
    Thursday, June 26, 2008 4:58 PM

Answers

  • Sorry Alex - but I think *you* misread the OP. We are talking about variables declared in the constructor - this was later clarified by the underline. You claimed that they are not thread safe ("NO"). Well: sorry, but you are wrong; they are - unless you go severly out of your way, as per my deliberately fabricated example.

    Pointing out (with explanation) that you are incorrect is not changing any rules...

    Oh - and you highlight "ONE" instance of a class; my sample only has one instance (not counting the delegates and compiler-generated code). And as for trivial: quite the opposite. The "trivial" answer is that "YES" they are thread-safe. There are, however, some exceptions to the trivial case - as shown through a repeatable, complete example.
    Marc
    Thursday, June 26, 2008 10:59 PM

All replies

  • NO.

    I tried to post just NO but got a message that the body must be between 4 and 600000 chars long. Mine was just 3:)


    AlexB
    Thursday, June 26, 2008 5:13 PM
  • Eh?  Sorry Alex, that does not compute.  Did you reply to the wrong posting?
    Thursday, June 26, 2008 5:28 PM
  • Well,

    Well I might be wrong but I kind of disagree with Alex (he said it is not threadsafe BTW). I think it is thread safe because separate threads have their own memory stack. Meaning that local variables will not be shared between threads.

    The constructor is to me initializing/instantiating local variables that is not shared between the threads. In other words each thread create its own instance in its own stack (so they can't point to the same object in the heap, meaning they are thread safe).

    Well this is my theory. I have written a piece of code that seems to corroborate my thought (the variables do not get mixed up)

        class Program 
        { 
            static void Main(string[] args) 
            { 
                Car car1 = new Car("Ford EUR", "Escort", 5, 1800); 
                Car car2 = new Car("Ford", "Sierra", 4, 2300); 
                Thread t1 = new Thread(new ParameterizedThreadStart(ThreadConsummer)); 
                t1.Name = "thread1"
                Thread t2 = new Thread(new ParameterizedThreadStart(ThreadConsummer)); 
                t2.Name = "thread2"
                t1.Start(car1); 
                t2.Start(car2); 
                Console.WriteLine("Main thread finished"); 
                System.Console.ReadLine(); 
            } 
     
            static void ThreadConsummer(object obj) 
            { 
                Car car = (Car)obj; 
                Console.WriteLine("Thread: " + Thread.CurrentThread.Name); 
                Car c = new Car(car.Brand, car.Model, car.NumberofGears, car.Cc); 
                Console.WriteLine("Thread Car constructed: " + Thread.CurrentThread.Name + " : " + c.ToString()); 
            } 
        } 
     
        class Car 
        { 
            public string Brand; 
            public string Model; 
            public int NumberofGears; 
            public int Cc; 
     
            public Car(string brand, string model, int numberOfGears, int cc) 
            { 
                Brand = brand
                Model = model
                Thread.Sleep(1000); //sleep for 1 sec 
                NumberofGears = numberOfGears
                Cc = cc
            } 
     
            public override string ToString() 
            { 
                return Brand + " " + Model + " " + NumberofGears.ToString() + ":" + Cc.ToString(); 
            } 
        } 
             


    HTH,

    Francois Malgreve


    Thursday, June 26, 2008 6:25 PM
  • Francois, how can they be thread safe in GENERAL if when you try to access them from another thread you must use InvokeRequired and BeginInvoke to make the operation thread safe? Of course, unless they are static.

    I simply do not understand how for instance a property declared in the constructor in a class instance can be accessed from another thread without that?

    I may be wrong, but I feel that a chance that I am wrong is not great but I respect your opinion.

    Catsaremyfriends, (they are my friends also:), what do you mean by do not compute? I did not offer anything to compute. It is not a presctription to compute. It is a warning that if you  try to access any property declared in the constructor from another thread you will get an exception.

    As I mentioned above, it is not an iron clad belief but it is my strong opinion based on my experience.

    I just noticed that you were talking about local variables, meaning local to the class. The answer is again: NO. 


    AlexB
    Thursday, June 26, 2008 6:42 PM
  • Ok,

    Maybe I have misunderstood the original question. My point is that it is thread safe to have 2 separate instances of the Car object in 2 separated threads. As the threads have different stacks. I thought that the variables were local to the type the constructor belong to.

    Now if he means local variables inside the constructor, mhh yeah, how can they be accessed by separated threads? Sorry I have never used BeginInvoke and so I have no idea.

    So I guess I misunderstood the original question.

    Sorry for the confusion,

    Francois.
    Thursday, June 26, 2008 7:02 PM
  • I am a little lost in the details that you have provided but my suspicion is that they are not thread safe. 

    In general there must be some thread safety provided when the code is executed in the constructor.  For instance if two asynchronous threads create instances of the same class it must be guaranteed that each ends up with a reference to its own instance.

    I am just unsure that this protection would extend to variables declared as local in the constructor method.




    Aside to  Alex:

    OH!  Sorry, your comment about "I tried to post..." was misunderstood.  I thought it was referring to the question I posed and since it did not seem relevant I thought maybe your comment was in reference to some other post.  Maybe MSDN should change the lower limit of posts to 2 chars!


    "Does not compute" has its origins in the TV show Star Trek.  Whenever Commander Data was given a directive that he could not follow, his comment was "Sorry Captain, that does not compute" meaning "I do not understand".

    It was my (pathetic) attempt at humour.

    cats


    Thursday, June 26, 2008 7:39 PM
  •  OH!  Sorry, your comment about "I tried to post..."

    A cat lover does not to have apologize to me:) You'd been forgiven well before you posted that:)

    And I am very superficial on Star Treck since there are not any cats in there as far as I remember. So I missed that. I took it literally.


    AlexB
    Thursday, June 26, 2008 10:04 PM
  • Variables declared in the constructor *are* (unless you try very hard - see below) thread-safe. Two different threads creating separate copies of the same type will have completely different stacks and stack-frames, so unrelated variables.

    To risk thread-safety against *fields* (variables declared on the instance) you need to pass out an instance to "this" during the constructor, and then talk to that instance from 2 threads. You would know if you had done this.

    To risk thread-safety against variables of the constructor, they would have to be "captured variables", i.e. used in a delegate inside the constructor, and that delegate is then passed outside during construction. This means that the "variables" are actually fields on compiler-generated classes, thus susceptible to thread issues *if you do mad things*. Again, you would know if you had done this.

    So here is the most fabricated example showing that *technically* you can get a C# [captured] variable to be affected by threading... in reality this would be extremely unlikely.

    using System;  
    using System.Threading;  
    class Foo  
    {  
        public Foo()  
        {  
            int i = 0;  
            Console.WriteLine("Ctor: {0}; i = {1}", Thread.CurrentThread.ManagedThreadId, i);  
            Action action = () => {  
                Console.WriteLine("Action: {0}", Thread.CurrentThread.ManagedThreadId);    
                i++;  
            };  
            Program.DoOddStuff(action);  
            Thread.Sleep(1000);  
            Console.WriteLine("Ctor: {0}; i = {1}", Thread.CurrentThread.ManagedThreadId, i);  
        }  
     
    }  
    static class Program  
    {  
        internal static void DoOddStuff(Action action)  
        {  
            ThreadPool.QueueUserWorkItem(delegate { action(); });  
        }  
        static void Main()  
        {  
            new Foo();  
        }  
     

    Marc
    Thursday, June 26, 2008 10:30 PM
  • Marc, I don't think he meant that. What you are proposing is trivial, I think. I think what he meant was that if there is only ONE instance of a class, just ONE instance and there is a parallel thread and somebody from that other thread is trying to access those variables--this somebody will get an exception.

    Again, we must be talking about only ONE instance of a class, not two because your sample is trivial, I think.

    I may be superficial, I will have to reread what you posted, I am kind of in a hurry now. But I think you've changed the rules of the game and I was not ready for that.


    AlexB
    Thursday, June 26, 2008 10:40 PM
  • Sorry Alex - but I think *you* misread the OP. We are talking about variables declared in the constructor - this was later clarified by the underline. You claimed that they are not thread safe ("NO"). Well: sorry, but you are wrong; they are - unless you go severly out of your way, as per my deliberately fabricated example.

    Pointing out (with explanation) that you are incorrect is not changing any rules...

    Oh - and you highlight "ONE" instance of a class; my sample only has one instance (not counting the delegates and compiler-generated code). And as for trivial: quite the opposite. The "trivial" answer is that "YES" they are thread-safe. There are, however, some exceptions to the trivial case - as shown through a repeatable, complete example.
    Marc
    Thursday, June 26, 2008 10:59 PM
  • catsaremyfriends said:

    I For instance if two asynchronous threads create instances of the same class it must be guaranteed that each ends up with a reference to its own instance.

    I am just unsure that this protection would extend to variables declared as local in the constructor method.


    For the case at end (defined the poster of the question), I think that we can all agree that it is indeed thread safe. This is because each threads have their own stack.
    I just wanted to clarify so that a final answer to the original question is clear.

    Francois.
    Friday, June 27, 2008 10:17 AM
  • Hi Alex:  Yes, Marc had it right, sorry if you misunderstood my original post.

    Thanks all for your help,

    cats
    Friday, June 27, 2008 3:01 PM