Thread local storage and method local variables

In C #, each thread has its own stack space.

If so, why is the following code not thread safe? (This code is reported to be thread safe in this post: Locking in C #

class Foo 
{ 
    private int count = 0; 
    public void TrySomething()     
    { 
        count++; 
    } 
} 

      

Since count is an int (stack variable), will this value be allocated to a separate thread on its own stack, and therefore thread safe?

I probably missed something here, but I don't understand what is actually in stream storage if there are no stream variables for the stream?

Also, what about locally declared variables:

class Foo 
{ 
    public void TrySomething(object myObj)     
    { 
       var localVariable = new object();
       localVariable = myObj;
    } 
} 

      

What are the implications here for a local variable? Is it still heap based? Is it thread-safe?

+2


a source to share


3 answers


Count is a member variable of the class Foo

. Since it Foo

is a reference type, it is stored on the heap, not the stack.

If you only created 1 Foo

object and allowed two separate threads to call a method TrySomething()

, they would both call the method on the same object (stored in the heap) and both would try to increment the same member as part of that same object. (See Darin's sample code )



The difference between structs and classes is not whether they are stored on the heap or on the stack. This is a common misconception. Think of classes as pointers to storage on the heap. Think of structs since direct values ​​are stored locally. At a very simple level, this means that structures are often stored on the stack, this is certainly not true in all cases, as this example shows.

+3


a source


But the counter is not a stack variable; it is a member variable of the class. If you pass the instance reference to Foo

another thread, you are in a non-thread situation.

Stream Local Storage (TLS) is a completely different concept than member variables. TLS associates values ​​with a stream, not a specific class. Think of it as global variables (or static member variables of classes), except that they are only scoped visible within the same thread; other streams don't even see. They are not stored on the thread stack, but in a special area that is private to the thread.



However, there is still room for trouble. If you store a Foo

TLS link on a stream, it is initially invisible to other streams. If you somehow copy this link to another thread, you will again end up in an insecure situation, regardless of whether the first link is in TLS.
+2


a source


This code is not thread safe, because two threads can execute this method on the same instance Foo

, which means the variable count

will be the same:

var foo = new Foo();
new Thread(foo.TrySomething).Start();
new Thread(foo.TrySomething).Start();

      

The TrySomething method will execute concurrently on two different threads using the same variable count

, so every access to that variable count

must be synchronized:

public void TrySomething()     
{ 
    Interlocked.Increment(ref count);
} 

      

+2


a source







All Articles