gpt4 book ai didi

c# - 这里需要内存栅栏吗?

转载 作者:行者123 更新时间:2023-11-30 17:42:48 32 4
gpt4 key购买 nike

基本上我有以下情况:

var tmp1 = new MyObject() { A = i, B = 2 };
// ** write barrier here??
this.Obj = tmp1;

另一个线程可以做这样的事情:

var tmp = this.Obj;
// ** read barrier here??
use(tmp.A);

像“Obj”这样的对象只被写入一次,然后被多个线程读取(多次)。

我知道 Obj 在两个线程中都不会为空;我也不关心“this.Obj”的同步。我关心的是,一旦我阅读了引用文献 tmp = Obj,内容(例如 AB)也是有效的。

我的问题是:我是否需要在上面标记的位置设置内存屏障(例如 Thread.MemoryBarrier();)以确保这始终是隐含的?


看来大家不喜欢这个问题。

我的问题源于以下内容。我已经阅读了有关内存栅栏的内容,它们保证:(引述)

The processor executing the current thread cannot reorder instructions in such a way that memory accesses prior to the call to MemoryBarrier execute after memory accesses that follow the call to MemoryBarrier.

如果您查看代码,CPU/编译器可能能够重写代码:

var tmp1 = new MyObject();
tmp1.A = i;
tmp1.B = 2;
this.Obj = tmp1;

更糟的是:

var tmp1 = new MyObject();
this.Obj = tmp1;
tmp1.A = i;
tmp1.B = 2;

如果另一个线程拾取了最后一个 case,它可以从内存中读取 this.Obj,而 AB 仍然具有默认值值(value)。

请注意,这不仅仅是编译器能够重新排序的问题;这也是允许 CPU 重新排序的问题。

换句话说:(感谢@MattBurland)

是否保证在将 tmp1 分配给 this.Obj 之前运行对象初始化程序?或者我是否需要使用内存栅栏来手动确保这一点?

最佳答案

C# 规范仅保证重新排序不会影响当前线程看到的内容。因此,JIT 似乎可以自由地重新排序下面的操作 2-4,因为它不会影响生产者线程的行为:

  1. 创建一个新的MyObject
  2. i分配给成员A
  3. 2分配给成员B
  4. 将新对象分配给 this.Obj

因此,似乎第 3 步和第 4 步之间需要一个屏障。另一种选择是使 this.Obj volatile。这将确保在写入 this.Obj 之后不允许移动其他读取或写入,同时强制执行所需的顺序。

关于c# - 这里需要内存栅栏吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31611441/

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