Tag: 易失性

C#中’volatile’关键字的目的是什么?

在C#中volatile关键字的目的是什么? 我需要在哪里使用此关键字? 我看到了以下声明,但我无法理解为什么需要使用volatile ? internal volatile string UserName;

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

众所周知,与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 […]

VB.NET中的易失性等价物

可能重复: 如何在VB.net中指定volatile的等价物? 什么是C#“volatile”的VB.NET关键字? 如果没有关键字什么机制是等价的?

挥发性围栏演示?

我试图看看栅栏是如何应用的。 我有这个代码(无限期地阻止): static void Main() { bool complete = false; var t = new Thread(() => { bool toggle = false; while(!complete) toggle = !toggle; }); t.Start(); Thread.Sleep(1000); complete = true; t.Join(); // Blocks indefinitely } 写volatile bool _complete; 解决问题。 获得围栏: 获取栅栏可防止其他读/写在栅栏之前移动; 但是,如果我用箭头↓来说明它(想想箭头就可以把所有东西推开。) 所以现在 – 代码看起来像: var t = new Thread(() => { bool toggle […]

.NET中的可变新鲜度保证(易失性与易失性读取)

我读过很多关于volatile和VoletileRead(ReadAcquireFence)的矛盾信息(msdn,SO等)。 我理解那些内存访问重新排序的限制含义 – 我仍然完全混淆的是新鲜度保证 – 这对我来说非常重要。 msdn doc for volatile提及: (…)这可确保始终在字段中显示最新值。 用于volatile字段的msdn doc提及: 读取volatile字段称为volatile读取。 易失性读取具有“获取语义”; 也就是说,保证在指令序列之后的任何内存引用之前发生。 VolatileRead的.NET代码是: public static int VolatileRead(ref int address) { int ret = address; MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way. return ret; } 根据msdn MemoryBarrier doc内存屏障阻止重新排序。 然而,这似乎对新鲜度没有任何影响 – 对吗? 那怎样才能获得保鲜? 标记字段volatile与使用VolatileRead和VolatileWrite语义访问它有区别吗? 我目前正在执行我的性能关键代码,需要保证新鲜度,但读者有时会得到陈旧的价值。 我想知道如果标记状态不稳定会使情况不同。 EDIT1: […]

何时在线程安全锁定代码中使用’volatile’或’Thread.MemoryBarrier()’? (C#)

我什么时候应该使用volatile / Thread.MemoryBarrier()来保证线程安全?

在哪里放置围栏/内存屏障以保证新的读取/提交写入?

像许多其他人一样,我一直对易失性读/写和围栏感到困惑。 所以现在我想完全理解这些是做什么的。 因此,易失性读取应该(1)表现出获取语义,(2)保证读取的值是新鲜的,即它不是缓存值。 让我们关注(2)。 现在, 我已经读过 ,如果你想执行一个易失性读取,你应该在读取后引入一个获取栅栏(或一个完整的栅栏),如下所示: int local = shared; Thread.MemoryBarrier(); 这究竟是如何阻止读取操作使用以前缓存的值? 根据栅栏的定义(不允许读取/存储在栅栏上方/下方移动),我会在读取之前插入栅栏,防止读取穿过栅栏并及时向后移动(也就是说,缓存)。 如何防止读取被及时向前移动(或后续指令被及时向后移动)保证了易失性(新鲜)读取? 它有什么用? 类似地,我认为易失性写入应该在写入操作之后引入栅栏,从而阻止处理器及时向前移动写入(也就是说,延迟写入)。 我相信这会使处理器刷新对主内存的写入。 但令我惊讶的是, C#实现在写入之前引入了栅栏! [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations public static void VolatileWrite(ref int address, int value) { MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way. address = value; } 更新 根据这个例子 ,显然是从“坚果壳中的C#4”中取出的, 在写入之后放置的栅栏2应该强制写入立即刷新到主存储器,并且在读取之前放置的栅栏3应该保证一个新的阅读: class […]

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。