gpt4 book ai didi

c# - 了解 CLR 2.0 内存模型

转载 作者:IT王子 更新时间:2023-10-28 23:31:22 26 4
gpt4 key购买 nike

乔·达菲,给 6 rules that describe the CLR 2.0+ memory model (这是实际的实现,不是任何 ECMA 标准)我正在写下我试图解决这个问题的尝试,主要是作为一种橡皮躲避的方式,但如果我在逻辑上犯了错误,至少这里有人能够捕获它在它给我带来悲伤之前。

  • 规则 1:负载之间的数据依赖性并且商店永远不会受到侵犯。
  • 规则 2:所有商店都有发布语义,即没有负载或存储可以移动一。
  • 规则 3:所有 volatile 负载均获取,即没有加载或存储可能移到前一个。
  • 规则 4:无负载和商店可能会跨越一个完整的障碍(例如 Thread.MemoryBarrier,锁获取,Interlocked.Exchange,Interlocked.CompareExchange 等)。
  • 规则 5:加载和存储到堆可能永远不会被介绍。
  • 规则 6:只能删除加载和存储当合并相邻的负载和从/到同一地点的商店。

我正在尝试理解这些规则。

x = y
y = 0 // Cannot move before the previous line according to Rule 1.

x = y
z = 0
// equates to this sequence of loads and stores before possible re-ordering
load y
store x
load 0
store z

看这个,看来load 0 可以上移到load y 之前,但是store 可能根本不会重新排序。因此,如果一个线程看到 z == 0,那么它也会看到 x == y。

如果 y 是 volatile,则加载 0 不能在加载 y 之前移动,否则它可以。不稳定的商店似乎没有任何特殊属性,没有商店可以相互重新订购(这是一个非常强大的保证!)

完整的障碍就像沙中的一条线,装载和存储无法移动。

不知道第 5 条是什么意思。

我猜规则 6 的意思是如果你这样做:

x = y
x = z

那么 CLR 就可以同时删除对 y 的加载和对 x 的第一次存储。

x = y
z = y
// equates to this sequence of loads and stores before possible re-ordering
load y
store x
load y
store z
// could be re-ordered like this
load y
load y
store x
store z
// rule 6 applied means this is possible?
load y
store x // but don't pop y from stack (or first duplicate item on top of stack)
store z

如果 y 不稳定怎么办?我在规则中看不到任何禁止执行上述优化的内容。这并不违反双重检查锁定,因为两个相同条件之间的 lock() 可以防止负载移动到相邻位置,并且根据规则 6,这是唯一可以消除它们的时间。

所以我想我理解除了规则 5 之外的所有内容。任何人都想启发我(或纠正我或在上述任何内容中添加一些内容?)

最佳答案

Joe Duffy 在 Concurrent Programming on Windows 的 pp517-18 中讨论了规则 5 :

As an example of when a load might be introduced, consider this code:

MyObject mo = ...;
int f = mo.field;
if (f == 0)
{
// do something
Console.WriteLine(f);
}

If the period of time between the initial read of mo.field into variable f and the subsequent use of f in the Console.WriteLine was long enough, a compiler may decide it would be more efficient to reread mo.field twice. ... Doing this would be a problem if mo is a heap object and threads are writing concurrently to mo.field. The if-block may contain code that assumes the value read into f remained 0, and the introduction of reads could break this assumption. In addition to prohibiting this for volatile variables, the .NET memory model prohibits it for ordinary variables referring to GC heap memory too.

blogged about one important place where this matters : 引发事件的标准模式。

EventHandler handler = MyEvent;
if (handler != null)
handler(this, EventArgs.Empty);

为了防止在单独线程上删除事件处理程序时出现问题,我们读取 MyEvent 的当前值,并且仅在该委托(delegate)非空时调用事件处理程序。

如果可以引入从堆中读取,编译器/JIT 可能会决定最好再次读取 MyEvent,而不是使用会引入竞争条件的本地。

关于c# - 了解 CLR 2.0 内存模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2941249/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com