Xen*_*ate 7 .net c# multithreading volatile .net-4.5
考虑以下示例:
private int sharedState = 0;
private void FirstThread() {
Volatile.Write(ref sharedState, 1);
}
private void SecondThread() {
int sharedStateSnapshot = Volatile.Read(ref sharedState);
Console.WriteLine(sharedStateSnapshot);
}
Run Code Online (Sandbox Code Playgroud)
直到最近,我的印象是,只要FirstThread()真的执行过SecondThread(),这个程序除了1之外不能输出任何东西.
但是,我现在的理解是:
sharedStatesharedState到sharedStateSnapshot.或者,换句话说:
sharedState实际发布到所有处理器核心时,该写入之前的所有内容也将被释放,并且,sharedStateSnapshot获取地址中的值时; sharedState一定是已经被收购了.如果我的理解是正确的,那么sharedState如果写入FirstThread()还没有被释放,那么没有什么可以防止获得"陈旧" .
如果这是真的,我们如何才能真正确保(假设最弱的处理器内存模型,如ARM或Alpha),程序将始终打印1?(或者我在某个地方的心理模型中犯了错误?)
您的理解是正确的,并且您无法确保程序始终使用这些技术打印1.为了确保程序打印1,假设线程2在第一个线程之后运行,则每个线程需要两个栅栏.
实现这一目标的最简单方法是使用lock关键字:
private int sharedState = 0;
private readonly object locker = new object();
private void FirstThread()
{
lock (locker)
{
sharedState = 1;
}
}
private void SecondThread()
{
int sharedStateSnapshot;
lock (locker)
{
sharedStateSnapshot = sharedState;
}
Console.WriteLine(sharedStateSnapshot);
}
Run Code Online (Sandbox Code Playgroud)
我想引用Eric Lippert的话:
坦率地说,我不鼓励你做一个不稳定的领域.易失性字段表明你正在做一些彻头彻尾的疯狂:你试图在两个不同的线程上读取和写入相同的值,而不是锁定到位.
这同样适用于呼叫Volatile.Read和Volatile.Write.实际上,它们甚至比volatile字段更糟糕,因为它们要求您手动执行volatile修改器自动执行的操作.
| 归档时间: |
|
| 查看次数: |
878 次 |
| 最近记录: |