What has changed in the memory model in .NET 4.5?

2019-03-29 10:21发布

问题:

I just read this puzzling line in Peter Richtie blog and I need help to understand the meaning Prior to .NET 4.5 you really programmed to the .NET memory model : http://msmvps.com/blogs/peterritchie/archive/2012/09/09/thread-synchronization-of-atomic-invariants-in-net-4-5.aspx

Has the 'usual' .NET memory model (such as the one discussed in Jeffrey Richter book CLR via C# edition 1 and 2 (I haven't read 3d)) changed in .NET 4.5?

Is there an article with conscious explanation?

回答1:

The proper way to handle concurrency in .NET is based on a weak memory model. This hasn't changed in .NET 4.5.

Just because Itanium is no longer supported doesn't mean you can assume the stronger x86 or amd64 memory models. For instance, you have other weak memory model platforms, such as ARM.

Always remember that non-volatile reads to the same variable or field may be elided after the first one by the JIT compiler, in case it can prove there is no synchronization between reads (memory barriers, monitor lock of an object that is/was monitor unlocked, volatile read of a variable that was volatile written, Interlocked operations on a variable). This respects the thread's point of view consistency.

The article you linked to shows examples where Microsoft .NET Framework's JIT compiler elides reads in e.g. while loops that read a non-volatile variable without any synchronization point inside the loop. But remember, a JIT compiler could use whole program optimizations to generalize this elision between callers and callees.

As such, lock-free algorithms in .NET that read a variable or field without memory barriers, locks, volatile semantics or Interlocked operations, on the premise that these reads will eventually see changes from other threads, are gambling with the JIT compiler. In essence, these algorithms are wrong in terms of portability.

Which makes me wonder, why do you ask this?