【发布时间】:2011-05-28 21:33:01
【问题描述】:
我正在寻找一个可重现的示例来演示 volatile 关键字的工作原理。我正在寻找在没有将变量标记为 volatile 且“正确”工作的情况下“错误”工作的东西。
我的意思是一些示例,它将证明执行期间的写入/读取操作顺序与变量未标记为易失性时的预期不同,而当变量未标记为易失性时也没有不同。
我以为我得到了一个示例,但后来在其他人的帮助下,我意识到这只是一段错误的多线程代码。 Why volatile and MemoryBarrier do not prevent operations reordering?
我还找到了一个链接,该链接演示了 volatile 对优化器的影响,但它与我正在寻找的不同。它表明对标记为 volatile 的变量的请求不会被优化出来。How to illustrate usage of volatile keyword in C#
这是我到目前为止的地方。此代码未显示任何读/写操作重新排序的迹象。我正在寻找一个会显示的。
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.CompilerServices;
namespace FlipFlop
{
class Program
{
//Declaring these variables
static byte a;
static byte 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++;
a = 0;
b = 0;
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)
{
WriteInOneDirection();
WriteInOtherDirection();
//Stops spinning in the Check method.
continueChecking = false;
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
static void WriteInOneDirection(){
a = 1;
b = 10;
}
[MethodImpl(MethodImplOptions.NoInlining)]
static void WriteInOtherDirection()
{
b = 20;
a = 2;
}
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;
}
}
}
}
}
编辑:
据我了解,导致重新排序的优化可能来自 JITer 或硬件本身。我可以改写我的问题。 JITer 或 x86 CPU 是否会重新排序读/写操作,如果有的话,有没有办法在 C# 中进行演示?
【问题讨论】:
-
很容易(在 x86 上)通过强制读取来举一个重要的例子;够了吗?还是您只是指订购?
-
(这里,关于强制读取 - 不像订购那么强大:stackoverflow.com/questions/458173/…)
-
正如我所说,我看到了那些帖子。我对重新排序示例感兴趣。
-
MSDN 示例与重新排序无关。这是关于“完成”领域的优化。
-
您可能还想关注 AMD 和 Itanium (iA64) 芯片:albahari.com/threading/part4.aspx#_The_volatile_keyword
标签: c# .net multithreading