Taking CPU caching and any possible compiler optimizations into account:
- Is it possible for “False” to be written to the console?
- Is option 1 setting up a memory fence that guarantees the freshness of the object reference and the field?
-
Is option 2 less “safe” than option 1 in any way?
class Program { class Test { internal bool value = false; } static void Main(string[] args) { Test test = new Test(); //Option 1 ThreadPool.QueueUserWorkItem((s) => { Thread.Sleep(1000); Console.WriteLine(((Test)s).value); }, test); //Option 2 ThreadPool.QueueUserWorkItem((s) => { Thread.Sleep(1000); Console.WriteLine(test.value); }); test.value = true; Console.ReadLine(); } }
Yes, of course. There is no synchronization to prevent either option #1 or option #2’s worker threads from printing out the
falsevalue before the main thread sets it totrue. While the contrived example uses a Thread.Sleep to prevent it from ever realistically occurring, there is no real synchronization here.No, option 1 is simply sending a reference to
sto the thread pool for forwarding to the delegate. Any memory fencing that happens should be considered an implementation detail, and as far as I am aware none occurs. There is certainly nothing (other than the aforementionedThread.Sleep()) preventing option #1’s worker thread from printing “false” before the main thread sets it to true.Option 2 is less safe in that you are closing over a variable which may be modified in a less contrived example. See Eric Lippert’s blog post on the subject of closing over loop variables– the same advice applies to option #2.