当前位置:  开发笔记 > 编程语言 > 正文

C#线程是否真的可以缓存一个值并忽略其他线程上该值的更改?

如何解决《C#线程是否真的可以缓存一个值并忽略其他线程上该值的更改?》经验,为你挑选了1个好方法。

这个问题不是关于竞争条件,原子性,或者为什么要在代码中使用锁.我已经知道了.

更新:我的问题不是"存在易失性存储器的奇怪现象"(我知道它确实存在),我的问题是"没有.NET运行时抽象,所以你永远不会看到它".

请参阅http://www.yoda.arachsys.com/csharp/threads/volatility.shtml 和关于字符串属性本身线程安全的第一个答案吗?

(它们实际上是同一篇文章,因为一个引用另一个.)一个线程设置bool而另一个线程循环永远读取bool - 那些文章声称读取线程可能缓存旧值并且从不读取新值,所以因此你需要一个锁(或使用volatile关键字).他们声称以下代码可能永远循环.现在我同意锁定变量是一种好习惯,但我无法相信.NET运行时会真正忽略内存值的变化,如文章所述.我理解他们关于易失性内存与非易失性内存的讨论,我同意他们在非托管中有一个有效的观点代码,但我无法相信.NET运行时将无法正确地抽象出来,以便下面的代码能够满足您的期望.这篇文章甚至承认代码"几乎可以肯定"有效(虽然不能保证),所以我就索赔要求BS.任何人都可以验证以下代码是否真的有效?是否有人能够得到一个案例(也许你不能总是重现它)这个失败的地方?

class BackgroundTaskDemo
{
    private bool stopping = false;

    static void Main()
    {
        BackgroundTaskDemo demo = new BackgroundTaskDemo();
        new Thread(demo.DoWork).Start();
        Thread.Sleep(5000);
        demo.stopping = true;
    }

    static void DoWork()
    {
         while (!stopping)
         {
               // Do something here
         }
    }
}

Marc Gravell.. 49

关键是:它可能有效,但不能保证按规范工作.人们通常遵循的是代码,这些代码适用于正确的原因,而不是通过编译器,运行时和JIT的混合组合工作,这可能会在框架版本,物理CPU,平台和x86之类的东西之间发生变化. 64.

理解记忆模型是一个非常复杂的领域,我并不认为自己是专家; 但人们谁真正的专家在这方面向我保证,你所看到的行为是不能保证.

您可以发布任意数量的工作示例,但不幸的是,除了"它通常有用"之外,这并不是很多.这当然不能证明它是保证工作.它只需要一个反例来反驳,但发现它就是问题......

不,我没有一只手.


使用可重复的反例进行更新:

using System.Threading;
using System;
static class BackgroundTaskDemo
{
    // make this volatile to fix it
    private static bool stopping = false;

    static void Main()
    {
        new Thread(DoWork).Start();
        Thread.Sleep(5000);
        stopping = true;


        Console.WriteLine("Main exit");
        Console.ReadLine();
    }

    static void DoWork()
    {
        int i = 0;
        while (!stopping)
        {
            i++;
        }

        Console.WriteLine("DoWork exit " + i);
    }
}

输出:

Main exit

但仍然在满CPU运行; 请注意,此时stopping已设定true.的ReadLine是,这样的过程不会终止.优化似乎取决于循环内代码的大小(因此i++).它只能在"发布"模式下工作.添加volatile,一切正常.



1> Marc Gravell..:

关键是:它可能有效,但不能保证按规范工作.人们通常遵循的是代码,这些代码适用于正确的原因,而不是通过编译器,运行时和JIT的混合组合工作,这可能会在框架版本,物理CPU,平台和x86之类的东西之间发生变化. 64.

理解记忆模型是一个非常复杂的领域,我并不认为自己是专家; 但人们谁真正的专家在这方面向我保证,你所看到的行为是不能保证.

您可以发布任意数量的工作示例,但不幸的是,除了"它通常有用"之外,这并不是很多.这当然不能证明它是保证工作.它只需要一个反例来反驳,但发现它就是问题......

不,我没有一只手.


使用可重复的反例进行更新:

using System.Threading;
using System;
static class BackgroundTaskDemo
{
    // make this volatile to fix it
    private static bool stopping = false;

    static void Main()
    {
        new Thread(DoWork).Start();
        Thread.Sleep(5000);
        stopping = true;


        Console.WriteLine("Main exit");
        Console.ReadLine();
    }

    static void DoWork()
    {
        int i = 0;
        while (!stopping)
        {
            i++;
        }

        Console.WriteLine("DoWork exit " + i);
    }
}

输出:

Main exit

但仍然在满CPU运行; 请注意,此时stopping已设定true.的ReadLine是,这样的过程不会终止.优化似乎取决于循环内代码的大小(因此i++).它只能在"发布"模式下工作.添加volatile,一切正常.

推荐阅读
mobiledu2402851323
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有