Reader Questions on Threads

I received a couple reader questions from my last Visual Studio Magazine article (link here). I thought they would be of general interest, so I'll answer them here:

1- you write: "The new object is created, and initialized before it is assigned to the internal member. This ensures that the entire object is updated in one operation." Are you saying that no context switch happens during class construction?

Or do you mean that it doesn't matter if it does, the object would remain consistent because the class has no mutation operations and the assignment to variable is atomic?

 

A context switch can happen during the constructor, but it doesn't matter because you can't manipulate the object until the constructor has completely finished. For example, if I write:

 

MyType foo = new MyType();

foo.DoThatVoodooThatYouDoSoWell();

 

There may very well be context switches that happen while MyType's constructor is executing. But it doesn't matter, because the last thing that happens is that foo is assigned to that new MyType. Until that assignment happens, no code (in any thread) can modify or access foo. So we're ok. Once construction has happened, immutability matters because now more than one thread may access foo. Context switches during any arbitrary mutator method on foo may leave the object in an inconsistent state.

 

2- I believe the consensus is that volatile variables are thread-safe, but what does that mean? Aren't all types (at least integral ones) thread-safe on atomic operations (i.e. assignments)?

 

That's true for most integral types. There are two actions that can cause problems. First, suppose a type is large enough that it takes more than one machine instruction to perform the assignment. (Consider a point with X,Y coordinates). That's two machine instructions to do the assignment (Assign X, Assign Y). A context switch between the two assignments means that you've got the point in an inconsistent state.

Secondly, consider an assignment where the lvalue also appears as the rvalue. The classic example is a bank balance:

balance = balance + depositAmount;

In machine instructions this will equate to (roughly)

  1. Fetch balance from memory and store in a register
  2. Put depositAmount in another register.
  3. Perform the add
  4. Put the result back in the memory location used for the balance

If a context switch occurs anytime after 1) and before 4), you run the risk of performing the calculation on the wrong value. Even though the assignment is atomic, the entire operation is several actions.

 

Thanks for the questions, and I hope that helps.

Published 03 September 2007 05:09 PM by wwagner
Filed under: ,
Ads by Lake Quincy Media

Comments

No Comments

Search

Go

Blog Group Links

Nascar style badges