Tag: 内存模型

写一个锁是否保证在另一个线程中读取新内容? (.Net,内存模型)

假设我有一个属性,其setter受锁保护,但没有任何锁定在getter周围,例如 private long _myField; public long MyProperty { get { return _myField; } set { lock(whatever) _myField = value; } } 除了同步写入(但不是读取)之外,锁定或者说Monitor.Exit应该导致易失性写入 。 我们现在说我们有两个线程A和B,并且发生以下序列: A读取MyProperty的当前值。 B将新值写入MyProperty 。 A再次读取MyProperty的当前值。 问:A现在可以保证看到新值吗? 或者我们的锁只是确保B及时写入主内存,而不是其他线程读取新值? 或者答案可能取决于我们是在运行.Net 2+还是“弱”的ECMA实施?

内存模型:防止存储释放和负载获取重新排序

众所周知,与Java的易失性不同,.NET的版本允许使用来自另一个位置的以下易失性读取来重新排序易失性写入。 当它出现问题时,建议将MemoryBarier置于它们之间,或者可以使用Interlocked.Exchange而不是volatile write。 它可以工作,但MemoryBarier在高度优化的无锁代码中使用时可能会成为性能杀手。 我想了一下,想出了一个主意。 我希望有人告诉我,我是否采取了正确的方式。 所以,想法如下: 我们希望防止这两种访问之间的重新排序: volatile1 write volatile2 read 从.NET MM我们知道: 1) writes to a variable cannot be reordered with a following read from the same variable 2) no volatile accesses can be eliminated 3) no memory accesses can be reordered with a previous volatile read 为了防止写入和读取之间不必要的重新排序,我们从刚刚写入的变量中引入了一个虚拟易失性读取: A) volatile1 write B) volatile1 […]

是否可以从另一个线程观察部分构造的对象?

我经常听说在.NET 2.0内存模型中,写入总是使用释放围栏。 这是真的? 这是否意味着即使没有明确的内存屏障或锁定,也不可能在不同于创建它的线程上观察部分构造的对象(仅考虑引用类型)? 我显然排除了构造函数泄漏this引用的情况。 例如,假设我们有不可变的引用类型: public class Person { public string Name { get; private set; } public int Age { get; private set; } public Person(string name, int age) { Name = name; Age = age; } } 是否可以使用以下代码观察除“John 20”和“Jack 21”之外的任何输出,例如“null 20”或“Jack 0”? // We could make this volatile to freshen the read, […]

Thread.VolatileRead实现

我正在研究VolatileRead / VolatileWrite方法的实现(使用Reflector),我对此感到困惑。 这是VolatileRead的实现: [MethodImpl(MethodImplOptions.NoInlining)] public static int VolatileRead(ref int address) { int num = address; MemoryBarrier(); return num; } 为什么在读取“地址”的值后放置内存屏障? 不应该是相反的吗? (在读取值之前放置,所以对于“address”的任何挂起写入都将在我们进行实际读取时完成。同样的事情发生在VolatileWrite,其中内存屏障位于赋值之前 。为什么?另外,为什么这些方法具有NoInlining属性?如果它们被内联会发生什么?

Interlocked.CompareExchange是否使用内存屏障?

我正在阅读Joe Duffy关于Volatile读取和写入以及及时性的post,我正在尝试理解post中最后一个代码示例: while (Interlocked.CompareExchange(ref m_state, 1, 0) != 0) ; m_state = 0; while (Interlocked.CompareExchange(ref m_state, 1, 0) != 0) ; m_state = 0; … 执行第二次CMPXCHG操作时,它是否使用内存屏障来确保m_state的值确实是写入它的最新值? 或者它只是使用已存储在处理器缓存中的某些值? (假设m_state未声明为volatile)。 如果我理解正确,如果CMPXCHG不会使用内存屏障,那么整个锁获取过程将不公平,因为第一个获取锁的线程很可能是将获得所有锁的线程。 以下锁 。 我理解正确,还是我错过了什么? 编辑 :主要问题实际上,在尝试读取m_state的值之前,调用CompareExchange是否会导致内存障碍。 因此,当尝试再次调用CompareExchange时,是否所有线程都可以看到赋值0。