views:

212

answers:

3
+2  A: 

But count isn't a stack variable; it's a member variable of a class. If you pass a reference to an instance of Foo to another thread, you are in a non-thread-safe situation.

Thread Local Storage (TLS) is a wholly different concept than member variables. TLS associates values with the thread and not with a specific class. Think of it as global variables (or static member variables of classes), except that they are scoped to only be visible within a single thread; other threads can't even see then. They are not stored in the thread's stack, but in a special area that is private to the thread.

There still is room for trouble, though. If you store a reference to a Foo in TLS in a thread it's initially invisible to other threads. If you then somehow copy that reference into another thread, you again are in a thread-unsafe situation, regardless of the fact that the first reference lives in TLS.

John Källén
+2  A: 

This code is not thread safe because two threads can execute this method on the same instance of Foo, meaning that the count variable will be the same:

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

The TrySomething method will be executed concurrently on two different threads using the same count variable, so every access to this count variable has to be synchronized:

public void TrySomething()     
{ 
    Interlocked.Increment(ref count);
} 
Darin Dimitrov
+1 Good answer. I like the code samples, and the suggested fix.
Simon P Stevens
The question is about thread local storage though.
John Källén
+3  A: 

Count is a member variable of the class Foo. As Foo is a reference type it is stored on the heap not the stack.

If you created only 1 Foo object and allowed two separate threads to call the TrySomething() method, they would both be calling the method on the same object (stored on the heap), and both would attempt to increment the same member as it's 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 the stack. This is a common misconception. Think of classes as pointers to storage on the heap. Think of structs as direct values being stored locally. At a very simple level, this does mean that structs are often stored on the stack, it's certainly not true in all cases as this example shows.

Simon P Stevens
this suggests, however, that any variable contained within a class is actually stored on the heap, and stack-based only member variables in stack-based structs are actually on the stack. is this true?
miguel
@Miguel: Don't think of them as "stack-based" variables. This is where the confusion starts. It's value types (structs) and reference types (classes). There is no requirement that either be stored anywhere in particular. As your code shows, structs can be on the heap. The difference is really about copy-semantics vs reference-semantics, it's nothing to do with storage location. Forget about stacks and heaps. I suggest you read [this by Eric Lippert](http://blogs.msdn.com/ericlippert/archive/2009/04/27/the-stack-is-an-implementation-detail.aspx).
Simon P Stevens
good stuff, thanks very much!
miguel