gpt4 book ai didi

c# - 在 C# 中对结构进行装箱/拆箱是否可以产生与原子结构相同的效果?

转载 作者:太空狗 更新时间:2023-10-30 01:02:42 25 4
gpt4 key购买 nike

根据 C# 规范,是否可以保证 foo.Bar 具有相同的原子效果(即从不同线程读取 foo.Bar 永远不会当被不同的线程写入时看到部分更新的结构)?

我一直认为它确实如此。如果确实如此,我想知道规范是否保证了这一点。

    public class Foo<T> where T : struct
{
private object bar;

public T Bar
{
get { return (T) bar; }
set { bar = value; }
}
}

// var foo = new Foo<Baz>();

编辑:@vesan 这不是 Atomic Assignment of Reference Sized Structs 的副本.这个问题询问装箱和拆箱的效果,而另一个问题是关于结构中的单个引用类型(不涉及装箱/拆箱)。这两个问题之间唯一的相似之处是结构和原子这两个词(你真的读过这个问题了吗?)。

EDIT2:这是基于 Raymond Chen 的回答的原子版本:

public class Atomic<T> where T : struct
{
private object m_Value = default(T);

public T Value
{
get { return (T) m_Value; }
set { Thread.VolatileWrite(ref m_Value, value); }
}
}

EDIT3:4 年后重温此内容。原来CLR2.0+的内存模型声明All write have the effect of volatile write: https://blogs.msdn.microsoft.com/pedram/2007/12/28/clr-2-0-memory-model/

因此,这个问题的答案应该是“如果硬件不对写入重新排序,它原子的”,而不是 Raymond 的答案。 JIT 和编译器无法重新排序写入,因此基于 Raymond 答案的“原子版本”是多余的。在弱内存模型架构上,硬件可能会重新排序写入,因此您需要适当的获取/释放语义。

EDIT4:同样,这个问题归结为 CLR 与 CLI (ECMA),后者定义了一个非常弱的内存模型,而前者实现了一个强大的内存模型。虽然不能保证运行时会执行此操作,但答案仍然有效。然而,由于绝大多数代码过去和现在都是为 CLR 编写的,我怀疑任何试图创建新运行时的人都会采取更简单的方法并以牺牲性能为代价实现强大的内存模型(这只是我自己的观点)。

最佳答案

不,结果不是原子的。虽然对引用的更新确实是原子的,但它不是同步的。可以在装箱对象内的数据变得可见之前更新引用。

让我们把事情分开。盒装类型 T 基本上是这样的:

class BoxedT
{
T t;
public BoxedT(T value) { t = value; }
public static implicit operator T(BoxedT boxed) { return boxed.t; }
}

(不完全是,但对于本次讨论的目的来说已经足够接近了。)

当你写作时

bar = value;

这是

的简写
bar = new BoxedT(value);

好的,现在让我们拆开这个作业。涉及多个步骤。

  1. BoxedT 分配内存。
  2. 使用 value 的副本初始化 BoxedT.t 成员。
  3. bar 中保存对 BoxedT 的引用。

第 3 步的原子性意味着当您从 bar 读取时,您将获得旧值或新值,而不是两者的混合。但它不能保证同步。特别是,操作 3 可能在操作 2 之前对其他处理器可见。

假设 bar 的更新对另一个处理器可见,但 BoxedT.t 的初始化不可见。当该处理器尝试通过读取 Boxed.t 值来拆箱 BoxedT 时,不能保证读取 t 的完整值写在步骤2中,可能只得到一部分值,另一部分包含default(T)

这基本上与双重检查锁定模式相同的问题,但更糟糕的是因为你根本没有锁!解决方案是使用释放语义更新 bar,以便在更新 bar 之前将所有先前的存储提交到内存。根据 C# 4 语言规范第 10.5.3 节,这可以通过将 bar 标记为 volatile 来完成。 (这也意味着所有从 bar 读取的内容都将获得语义,这可能是也可能不是您想要的。)

关于c# - 在 C# 中对结构进行装箱/拆箱是否可以产生与原子结构相同的效果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32728976/

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