【发布时间】:2011-06-09 11:32:29
【问题描述】:
在如下代码中,如果 Proc1 和 Proc2 在不同的处理器上同时执行,ThingVal2 是否有可能获得 5 以外的值(例如零)?
类 SimpleThing 公共 X 作为整数 Sub New(ByVal value As Integer) X = 价值 结束子 结束类 类并发测试 Dim Thing1 作为新的 SimpleThing(5) Dim Thing2 作为新的 SimpleThing(0) 将 ThingRef 调暗为 SimpleThing = Thing1 将 ThingVal1、ThingVal2 调暗为整数 子程序1() 事物2.X = 5 Threading.Thread.MemoryBarrier() ThingRef = Thing2 结束子 子进程2() ThingVal1 = Thing2.X ThingVal2 = ThingRef.X 结束子 结束类我知道在像 IA64 这样的弱模型中,Proc2 很有可能会看到 ThingRef 发生了变化,但看不到 Thing2 的字段 X 发生了变化。在 x86 或 x64 上运行的 .Net 应用程序是否存在这种风险?如果 Proc1 创建了一个 SimpleThing 的新实例,将其 X 字段设置为 5,然后将 ThingRef 设置为指向它,这是否足以避免危险,或者是否有可能将新事物分配在缓存行上与 Proc2 线程访问过的其他内容共享?
多线程代码的一个常见范例是构造一个不可变对象并设置一个可变引用来指向它(可能使用 Interlocked.CompareExchange)。在 x86/x64 下读取不可变类型而不考虑线程是否总是安全的,还是会导致问题?如果是后者,在 vb.net 中保证可靠行为的首选方式是什么?
另外,是否有任何方法可以指定代码必须以不会发生此类问题的方式运行(例如,在无法保证正确运行的 IA64 等设备上将执行限制为单个内核)?
【问题讨论】:
-
只有在一个周期内可以读取值时才能保证不可变。 Int 和 bool 属于该类别。不太确定 long,绝对不是字符串。
-
@SRM:不可变对象是一个一旦引用可供其他任何人使用就永远不会改变的对象。上面的“SimpleThing”对象不是不可变的,因为我试图准确地询问在 .net x86 和 .net x64 内存模型下什么是保证和不保证。
标签: vb.net x86 64-bit memory-model memory-barriers