【发布时间】:2019-03-18 10:39:12
【问题描述】:
给定以下类:
class C
{
public int x = 0;
public void F() {
new Thread(G).Start();
while (x == 0) { Thread.Sleep(TimeSpan.FromMilliseconds(1)); }
}
public void G() {
Thread.Sleep(TimeSpan.FromMilliseconds(1000));
Interlocked.Exchange(ref x, 1);
}
}
我假设在C# 标准下允许new C().F() 永远运行是的,因为没有什么可以强制F() 在每次访问时从主内存中检索x 的值。这里的Interlocked.Exchange 甚至没有帮助,因为F() 没有看到G() 的实现,因此可能会优化主内存的访问。
这个分析正确吗?
此外,我知道让x volatile 可以解决这个问题,但是还有什么可以解决这个问题的吗?
【问题讨论】:
-
不要在 C# 中使用
volatile,除非你真的,真的知道你的方法:stackoverflow.com/a/19384758/1086121。一个普通的lock声明是解决这个问题的方法。 -
正如 canton7 提到的,锁定对象将迫使其他线程等待(因此同步)锁定线程释放它,从而使其成为原子。
-
写入被其他线程看到。假设有 其他线程可以查看写入 -
new Thread(G).Start();创建一个孤立的线程对象,该对象将被垃圾收集 -
即使解决了,阅读也需要同步,通过锁或
Interlocked.CompareExchange -
您也可以使用
Thread.VolatileWrite和Thread.VolatileRead(作为volatile关键字的替代品)。Interlocked.Exchange这里根本不需要,因为 int32 分配是原子的。
标签: c# multithreading thread-synchronization