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();
}
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
.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With