挥发性用法的可再现的例子 [英] A reproducable example of volatile usage

查看:257
本文介绍了挥发性用法的可再现的例子的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我寻找一个可重复的例子,可以说明如何volatile关键字的工作原理。我在找的东西,作品错不变量(S)标记为易失性和工作正确的程度。

I am look for a reproducible example that can demonstrate how volatile keyword works. I'm looking for something that works "wrong" without variable(s) marked as volatile and works "correctly" with it.

我的意思是一些例子,将展示的执行过程中读/写操作的顺序是不同的预期时,变量未标记为易挥发,而不是不同的,当变量未标记为易失性。

I mean some example that will demonstrate that order of write/read operations during the execution is different from expected when variable is not marked as volatile and is not different when variable is not marked as volatile.

我觉得我得到了一个例子,但然后用别人的帮助我意识到,这仅仅是一张错误的多线程code。 <一href="http://stackoverflow.com/questions/6162996/why-volatile-and-memorybarrier-do-not-$p$pvent-operations-reordering">Why易失性和MemoryBarrier没有prevent操作重新排序?

I thought that I got an example but then with help from others I realized that it just was a piece of wrong multithreading code. Why volatile and MemoryBarrier do not prevent operations reordering?

我还发现,展现了动荡的优化产生影响的链接,但它是我在寻找什么不同。这表明,标记为挥发性的请求变量将不被优化掉了。<一个href="http://stackoverflow.com/questions/133270/how-to-illustrate-usage-of-volatile-keyword-in-c">How说明在C# volatile关键字的使用

I've also found a link that demonstrates an effect of volatile on the optimizer but it is different from what I'm looking for. It demonstrates that requests to variable marked as volatile will not be optimized out.How to illustrate usage of volatile keyword in C#

下面是我得到了这么远。这code不显示的读/写操作重新排序的任何迹象。我正在寻找一个将显示出来。

Here is where I got so far. This code does not show any signs of read/write operation reordering. I'm looking for one that will show.

    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#中,如果他们这样做?

As I understand an optimization that causes reordering can come from JITer or from hardware itself. I can rephrase my question. Does JITer or x86 CPUs reorder read/write operations AND is there a way to demonstrate it in C# if they do?

推荐答案

中的挥发性的是一个抖动的实现细节的精确语义。编译器会发出欧普codes.Volatile IL指令在任何你访问该声明为易挥发的变量。它做了一些检查,以验证该变量的类型是合法的,你不能声明值类型大于4个字节的挥发性但这是真正的老板。

The exact semantics of volatile is a jitter implementation detail. The compiler emits the Opcodes.Volatile IL instruction where ever you access a variable that's declared volatile. It does some checking to verify that the variable type is legal, you can't declare value types larger than 4 bytes volatile but that's where the buck stops.

C#语言规范定义的挥发性的<一个行为href="http://stackoverflow.com/questions/4103415/what-is-the-purpose-of-volatile-keyword-in-c/4103879#4103879">quoted在这里通过埃里克利珀。在发布和获取的语义是什么,只能使与内存模型弱的处理器核心意义。这些类型的处理器并没有在市场上做得很好,可能是因为他们是如此巨大的痛苦进行编程。您的code将永远运行在一个钛的几率是很小的。

The C# language specification defines the behavior of volatile, quoted here by Eric Lippert. The 'release' and 'acquire' semantics is something that only makes sense on a processor core with a weak memory model. Those kind of processors have not done well in the market, probably because they are such an enormous pain to program. The odds that your code will ever run on a Titanium are slim to none.

什么是关于C#语言规范定义,尤其糟糕的是,它没有提及在所有什么的真正的发生。声明一个变量挥发性prevents从优化code存储变量在CPU寄存器中的抖动优化。这就是为什么马克挂钩code是挂。这只会发生在当前的x86抖动,另一种强烈暗示的挥发性的是一个真正的抖动实现细节。

What's especially bad about the C# language specification definition is that it doesn't mention at all what really happens. Declaring a variable volatile prevents the jitter optimizer from optimizing the code to store the variable in a cpu register. Which is why the code that Marc linked is hanging. This will only happen with the current x86 jitter, another strong hint that volatile is really a jitter implementation detail.

贫困语义的挥发性的拥有丰富的历史,它来自于C语言。谁的code发电机有很多的麻烦得到它的权利也是如此。这里有一个关于它(PDF)一个有趣的报告。它建于2008年,一个良好的30年以上的机会得到它的权利。还是错,这正好腹起来的时候code优化是忘记了一个变量是挥发性的。未优化code从来没有与它的问题。值得注意的是,在开源版本的.NET(SSLI20)的抖动完全忽略了IL指令。它也可以争辩说,在x86抖动的当前行为是一个错误。我想是的,它是不容易碰到它进入故障模式。但是,没有人可以说,它实际上的的一个bug。

The poor semantics of volatile has a rich history, it comes from the C language. Whose code generators have lots of trouble getting it right as well. Here's a interesting report about it (pdf). It dates from 2008, a good 30+ years of opportunity to get it right. Or wrong, this goes belly-up when the code optimizer is forgetting about a variable being volatile. Unoptimized code never has a problem with it. Notable is that the jitter in the 'open source' version of .NET (SSLI20) completely ignores the IL instruction. It can also be argued that the current behavior of the x86 jitter is a bug. I think it is, it is not easy to bump it into the failure mode. But nobody can argue that it actually is a bug.

写作是在墙壁上,只有永远声明变量挥发性如果它被存储在一个存储器映象寄存器。关键字的初衷。你会遇到在C#语言这种用法的可能性应该是微乎其微,code一样,属于一个设备驱动程序。最重要的是,从来没有的假设它是在多线程情况下是有用的。

The writing is on the wall, only ever declare a variable volatile if it is stored in a memory mapped register. The original intention of the keyword. The odds that you'll run into such a usage in the C# language should be vanishingly small, code like that belongs in a device driver. And above all, never assume that it is useful in a multi-threading scenario.

这篇关于挥发性用法的可再现的例子的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆