In C# 2.0+, is it necessary to lock around a closure that another thread will execute? Specifically, in the example below, is the locking necessary to ensure that the Maint thread flushes its value of x to shared memory and that thread t reads its value of x from shared memory?
I think it is, but if I’m wrong, please reference e.g. an authoritative (e.g., MSDN) article indicating why not. Thanks!
delegate void Foo(); public static void Main() { Foo foo = null; object guard = new object(); int x = 1; lock (guard) { foo = () => { int temp; lock (guard) temp = x; Console.WriteLine(temp); }; } Thread t = new Thread(() => foo()); t.Start(); t.Join(); }
Edit: Clarified that I want to know for C# 2.0+, which is to say that the .NET 2.0+’s stronger memory model (than ECMA 335 CLI) is in effect.
Calling any constructor has release semantics in the .NET memory model. (Not in the CLI memory model, but in the .NET one.) So by calling the
Threadconstructor – and the delegate constructor itself – I believe you’re okay. If you set x to 1 after the final constructor I’d be less sure. (EDIT: It’s possible that the constructor business is more to do with the new Java memory model than .NET, given the later stuff about writes…)In fact, I have a suspicion that all writes have release semantics (again, in the implemented .NET memory model) but not all reads have acquire semantics. In other words, the data will always be available to other threads, but it might not be used by those threads. In this case the new thread won’t ‘have’ the old value of the variable – there’s no way it could have logically read the value before it started, so you’re safe on that front.
I can check up on the ‘all writes’ side of things – I suspect there’s something in Joe Duffy’s blog or book about it.
EDIT: From ‘Concurrent Programming on Windows’ P516:
I believe that’s enough. I suspect that there are very few people on Stack Overflow who are capable of saying for sure – I wouldn’t fully trust many people who aren’t in the MS CLR or concurrency teams, except maybe Jeff Richter.