事实证明代码示例失败,没有易失性 [英] Code example proven to fail w/o volatile

查看:51
本文介绍了事实证明代码示例失败,没有易失性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是一个C#代码示例,至少是在Mac OS X 10.9上,它是损坏的Java代码的逐字翻译(事实证明该代码已损坏(即第二个线程可能无法观察到sharedValue值的变化), Java 1.8(64位),Arrandale(1个插槽x 2个核心x 2 HT = 4个硬件线程):

Below is a C# code example which is a verbatim translation of a broken Java code (which has proven to break (i. e. the 2nd thread may fail to observe the change of sharedValue value) at least on Mac OS X 10.9, Java 1.8 (64 bit), Arrandale (1 socket x 2 core x 2 HT = 4 HW threads)):

using System;
using System.Threading;

class ThreadTest {
    /* volatile */ private int sharedValue;

    private void RunAsync() {
        while (this.sharedValue == 0);
    }

    private bool Test() {
        Thread t = new Thread(this.RunAsync);
        t.IsBackground = true;
        t.Start();

        Thread.Sleep(10);

        // Yes I'm aware the operation is not atomic
        this.sharedValue++;

        t.Join(10);
        bool success = !t.IsAlive;
        if (!success) {
            Console.Write('.');
        }
        return success;
    }

    static void Main() {
        long failureCount = 0L;
        const long testCount = 10000L;
        for (long i = 0; i < testCount; i++) {
            if (!new ThreadTest().Test()) {
                failureCount++;
            }
        }
        Console.WriteLine();
        Console.WriteLine("Failure rate: " + 100.0 * failureCount / testCount + "%");
    }
}

令人惊讶的是,无论我在.NET 4.0/Windows XP(32位)上运行上述C#代码多少次,都没有观察到任何故障.在Mac OS X的Mono(64位)上运行时,也没有任何故障.在两种情况下,我都只看到一个CPU内核处于繁忙状态.

Amazingly, no matter many times I run the above C# code on .NET 4.0/Windows XP (32 bit), I haven't observed a single failure. Nor is there any failure when running on Mono (64 bit), Mac OS X. In both cases, I only see a single CPU core busy.

您能建议一个C#代码示例,该示例错误使用共享变量并失败,除非将变量标记为volatile?

Can you suggest a C# code example which makes an incorrect use of a shared variable and fails unless the variable is marked volatile?

推荐答案

尝试运行以下程序的RELEASE版本(请勿从调试器运行该版本,否则演示将无法进行-因此,请通过"Debug"运行发行版本|无需调试即可开始"):

Try running the RELEASE build of the following program (do NOT run it from the debugger otherwise the demonstration won't work - so run the release build via "Debug | Start without debugging"):

using System;
using System.Threading;
using System.Threading.Tasks;

namespace Demo
{
    internal class Program
    {
        private void run()
        {
            Task.Factory.StartNew(resetFlagAfter1s);
            int x = 0;

            while (flag)
                ++x;

            Console.WriteLine("Done");
        }

        private void resetFlagAfter1s()
        {
            Thread.Sleep(1000);
            flag = false;
        }

        private volatile bool flag = true;

        private static void Main()
        {
            new Program().run();
        }
    }
}

该程序将在一秒钟后终止.

The program will terminate after a second.

现在从行中删除volatile

private volatile bool flag = true; // <--- Remove volatile from this

这样做之后,程序将永远不会终止. (在Windows 8 x64,.Net 4.5上测试)

After doing so, the program will now never terminate. (Tested on Windows 8 x64, .Net 4.5)

但是请注意,在某些情况下,使用Thread.MemoryBarrier()比声明变量volatile更合适,即:

Please note, however, that in some cases it is more appropriate to use Thread.MemoryBarrier() rather than declaring the variable volatile, i.e.:

while (flag)
{
    Thread.MemoryBarrier();
    ++x;
}

有关更多信息,请参见 http://blogs .msdn.com/b/brada/archive/2004/05/12/130935.aspx

For more information, see http://blogs.msdn.com/b/brada/archive/2004/05/12/130935.aspx

这篇关于事实证明代码示例失败,没有易失性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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