【发布时间】:2016-04-08 14:14:32
【问题描述】:
我已多次阅读threading manual 和相关的 MSDN 页面以及 SOquestions。尽管如此,我仍然不完全理解 Volatile.Read/Write 和联锁操作是否仅适用于相关变量,或者在该操作之前/之后的所有读/写。
例如,假设我有一个数组和一个计数器。
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,并在互锁增量之前设置一个实例字段。隐式完整围栏是否适用于该线程之前的所有读/写,还是仅适用于计数器?
我正在实施scalable reader/writer scheme,我在 Joe Duffy 的帖子中找到了以下声明:
如果受保护的变量是对堆对象的引用,则每次触摸字段时都需要担心使用读保护。就像锁一样,这种技术不会组合。与简单锁定以外的任何其他方法一样,请谨慎使用此技术;尽管内置的获取和释放栅栏可以保护您免受内存模型重新排序问题的影响,但您可能会陷入一些简单的陷阱。
这只是一个不鼓励使用低锁结构的一般声明,还是以某种方式适用于上面的示例?
【问题讨论】:
-
您只需要在此处获取/释放语义即可获得互锁增量提供的正确行为。保证是看到更新计数器的任何线程也将看到正在进行的写入。
-
如果你不理解它,那么你不应该,永远使用它。它不会工作,保证。使用熊陷阱,您不会发现它不起作用,只有您的用户会。请改用 ReaderWriterLockSlim 类,它是由了解它并知道如何使其尽可能最佳的人编写的。
-
@HansPassant 世界上有这样一种东西叫做
learning... SO 有助于解决这个问题:) 如果你阅读了关于读写锁实现的整个 Joe Duffy 文章系列,你会注意到数量级的性能差异。 -
所以你想比 Joe Duffy 更好......好吧,你肯定会学到一些你还不知道的东西。
-
@HansPassant 我不想变得更好,我只是 prefer 200 Mops over 15 Mops 当没有争用...诸如“你太愚蠢了”之类的答案只是 not constructive。跨度>
标签: c# .net multithreading memory-barriers