Hamlet Hakobyan
Hamlet Hakobyan

Reputation: 33391

Variable caching

Why in this part of code complete is cached?

static void Main()
{
  bool complete = false; 
  var t = new Thread (() =>
  {
    bool toggle = false;
    while (!complete) toggle = !toggle;
  });
  t.Start();
  Thread.Sleep (1000);
  complete = true;
  t.Join();        // Blocks indefinitely
}

but in this part it isn't?

static void Main()
{
  bool complete = false;
  bool toggle = false; 
  var t = new Thread (() =>
  {
    while (!complete) toggle = !toggle;
  });
  t.Start();
  Thread.Sleep (1000);
  complete = true;
  t.Join();  
}

Upvotes: 5

Views: 275

Answers (3)

Miserable Variable
Miserable Variable

Reputation: 28761

Don't be sure caching will happen on all architectures as above, or even that it will always happen as above in multiple runs of the program.

It could be because in the second case the lambda is modifying the closure, while in first it is only accessing the closure. Of course this is only a wild guess.

More importantly though, there are no guarantees about when caching will be done, memory boundary only specifies when the thread will not use cached value.

Bottom line, you cannot rely on caching to occur.

Upvotes: 3

usr
usr

Reputation: 171246

You are doing unsynchronized data sharing across threads. Sirens should now go off.

As I understand the memory model the JIT is allowed to read complete once and store it in a register. For that reason the update from Main never becomes visible.

As for fixing this, the simplest way is to wrap a lock around accesses to complete. You could also use Thread.VolatileRead and Thread.VolatileWrite.

Upvotes: 3

Xharze
Xharze

Reputation: 2733

Both samples complete in my case, but you're lambda/delegate can be compile differently in different compilers, which could be the problem.

You delegate are accessing a modified closure, which can cause a bunch of problems and you have apparently found one. Take a look at the answer provided by Jon Skeet here, Access to Modified Closure, it is not exactly the same problem, but the reason described here works in you case too.

Upvotes: 0

Related Questions