It is generally accepted (I believe!) that a lock will force any values from fields to be reloaded (essentially acting as a memory-barrier or fence - my terminology
Maybe I can help you this time... instead of using a volatile you can use Interlocked.Exchange with an integer.
if (closing==1) { // <==== (2) access field here
value = default(T);
return false;
}
// somewhere else in your code:
Interlocked.Exchange(ref closing, 1);
Interlocked.Exchange is a synchronization mechanism, volatile isn't... I hope that's worth something (but you probably already thought about this).