【发布时间】:2011-05-29 03:18:20
【问题描述】:
如果我正确理解 volatile 和 MemoryBarrier 的含义,那么下面的程序将永远无法显示任何结果。
每次我运行它时,它都会捕获写入操作的重新排序。我在 Debug 或 Release 中运行它并不重要。我将它作为 32 位或 64 位应用程序运行也没关系。
为什么会这样?
using System;
using System.Threading;
using System.Threading.Tasks;
namespace FlipFlop
{
class Program
{
//Declaring these variables as volatile should instruct compiler to
//flush all caches from registers into the memory.
static volatile int a;
static volatile int b;
//Track a number of iteration that it took to detect operation reordering.
static long iterations = 0;
static object locker = new object();
//Indicates that operation reordering is not found yet.
static volatile bool continueTrying = true;
//Indicates that Check method should continue.
static volatile bool continueChecking = true;
static void Main(string[] args)
{
//Restarting test until able to catch reordering.
while (continueTrying)
{
iterations++;
var checker = new Task(Check);
var writter = new Task(Write);
lock (locker)
{
continueChecking = true;
checker.Start();
}
writter.Start();
checker.Wait();
writter.Wait();
}
Console.ReadKey();
}
static void Write()
{
//Writing is locked until Main will start Check() method.
lock (locker)
{
//Using memory barrier should prevent opration reordering.
a = 1;
Thread.MemoryBarrier();
b = 10;
Thread.MemoryBarrier();
b = 20;
Thread.MemoryBarrier();
a = 2;
//Stops spinning in the Check method.
continueChecking = false;
}
}
static void Check()
{
//Spins until finds operation reordering or stopped by Write method.
while (continueChecking)
{
int tempA = a;
int tempB = b;
if (tempB == 10 && tempA == 2)
{
continueTrying = false;
Console.WriteLine("Caught when a = {0} and b = {1}", tempA, tempB);
Console.WriteLine("In " + iterations + " iterations.");
break;
}
}
}
}
}
【问题讨论】:
-
b/c 这是他们的想法。内存屏障(写)只是确保所有操作都被刷新,因此以下是有序的部分屏障。
-
代码中最有趣的是删除所有
Thread.MemoryBarrier();行可以解决您的问题=) -
@Mikant:不,那没有解决问题。它只是使它非常不可能。让它运行几天,它仍然可能发生。
标签: c# .net multithreading