.NET Volatile.Read/Write 和 Interlocked 作用域
.NET Volatile.Read/Write and Interlocked scope
threading manual and relevant MSDN pages and SO questions我已经读了好几遍了。尽管如此,我还是不完全理解 Volatile.Read/Write 和互锁操作是否仅适用于相关变量,或者所有 read/writes before/after 操作。
例如,假设我有一个数组和一个计数器。
long counter = 0;
var values = new double[1000000];
values[42] = 3.1415;
// Is this line needed instead of simple assignment above,
// or the implicit full-fence of Interlocked will guarantee that
// all threads will see the values[42] after interlocked increment?
//Volatile.Write(ref values[42], 3.1415);
Interlocked.Increment(ref counter);
互锁增量是否保证与我使用 Volatile.Write(ref values[42], 3.1415);
而不是 values[42] = 3.1415;
相同的结果。
如果我有一个引用类型数组怎么办,例如一些 POCO,并在互锁增量之前设置一个实例字段。隐式完全围栏是否适用于它之前的那个线程的所有 read/writes,还是仅适用于计数器?
我正在实施 scalable reader/writer scheme,我在 Joe Duffy post 中发现了以下语句:
If the variables protected are references to heap objects, you need to worry about using the read protection each time you touch a field. Just like locks, this technique doesn’t compose. As with anything other than simple locking, use this technique with great care and caution; although the built-in acquire and release fences shield you from memory model reordering issues, there are some easy traps you can fall into.
这只是一个不鼓励使用低锁结构的一般性陈述,还是以某种方式适用于上面的示例?
您可能缺少的是对栅栏的理解。这是阅读它们的最佳资源:http://www.albahari.com/threading/part4.aspx
简短的回答是 Interlocked.Increment
发出一个完整的栅栏,它独立于它正在更新的变量。我相信 Volatile.Write
问题半篱笆。可以从 Thread.MemoryBarrier
构建半个栅栏。当我们说 Interlocked.Increment
发出完整的栅栏时,这意味着 Thread.MemoryBarrier
在操作前后被调用。 Volatile.Write
在写入前调用 Thread.MemoryBarrier
,在写入后调用 Volatile.Read
。栅栏确定何时可以重新排序内存访问(并且它不是特定于变量的,因为 Thread.MemoryBarrier
是无参数的)。
threading manual and relevant MSDN pages and SO questions我已经读了好几遍了。尽管如此,我还是不完全理解 Volatile.Read/Write 和互锁操作是否仅适用于相关变量,或者所有 read/writes before/after 操作。
例如,假设我有一个数组和一个计数器。
long counter = 0;
var values = new double[1000000];
values[42] = 3.1415;
// Is this line needed instead of simple assignment above,
// or the implicit full-fence of Interlocked will guarantee that
// all threads will see the values[42] after interlocked increment?
//Volatile.Write(ref values[42], 3.1415);
Interlocked.Increment(ref counter);
互锁增量是否保证与我使用 Volatile.Write(ref values[42], 3.1415);
而不是 values[42] = 3.1415;
相同的结果。
如果我有一个引用类型数组怎么办,例如一些 POCO,并在互锁增量之前设置一个实例字段。隐式完全围栏是否适用于它之前的那个线程的所有 read/writes,还是仅适用于计数器?
我正在实施 scalable reader/writer scheme,我在 Joe Duffy post 中发现了以下语句:
If the variables protected are references to heap objects, you need to worry about using the read protection each time you touch a field. Just like locks, this technique doesn’t compose. As with anything other than simple locking, use this technique with great care and caution; although the built-in acquire and release fences shield you from memory model reordering issues, there are some easy traps you can fall into.
这只是一个不鼓励使用低锁结构的一般性陈述,还是以某种方式适用于上面的示例?
您可能缺少的是对栅栏的理解。这是阅读它们的最佳资源:http://www.albahari.com/threading/part4.aspx
简短的回答是 Interlocked.Increment
发出一个完整的栅栏,它独立于它正在更新的变量。我相信 Volatile.Write
问题半篱笆。可以从 Thread.MemoryBarrier
构建半个栅栏。当我们说 Interlocked.Increment
发出完整的栅栏时,这意味着 Thread.MemoryBarrier
在操作前后被调用。 Volatile.Write
在写入前调用 Thread.MemoryBarrier
,在写入后调用 Volatile.Read
。栅栏确定何时可以重新排序内存访问(并且它不是特定于变量的,因为 Thread.MemoryBarrier
是无参数的)。