为什么这个程序在布尔条件变量不存在波动的情况下不会进入无限循环?

2023-12-29

我想了解何时需要将变量声明为易失性。为此,我编写了一个小程序,并期望它由于缺少条件变量的波动性而进入无限循环。它没有进入无限循环,并且在没有 volatile 关键字的情况下工作正常。

两个问题:

  1. 我应该在下面的代码清单中更改什么 - 以便它绝对需要使用 易失性?

  2. C# 编译器是否足够聪明,可以将变量视为易失性变量 - 如果它发现正在从不同的线程访问变量?

以上引发了我更多的问题:)

A。挥发性只是一个提示吗?

b.在多线程上下文中什么时候应该将变量声明为 volatile?

C。对于线程安全类,是否应该将所有成员变量声明为 volatile?这太过分了吗?

代码清单(重点是波动性而不是线程安全):

class Program
{
    static void Main(string[] args)
    {
        VolatileDemo demo = new VolatileDemo();
        demo.Start();

        Console.WriteLine("Completed");
        Console.Read();
    }
}

    public class VolatileDemo
    {
        public VolatileDemo()
        {
        }

        public void Start()
        {
            var thread = new Thread(() =>
            {
                Thread.Sleep(5000);
                stop = true;
            });

            thread.Start();

            while (stop == false)
                Console.WriteLine("Waiting For Stop Event");
        }

        private bool stop = false;
    }

Thanks.


首先,乔·达菲说“不稳定就是邪恶” http://www.bluebytesoftware.com/blog/2010/12/04/SayonaraVolatile.aspx- 这对我来说已经足够了。

如果您确实想考虑易失性,则必须考虑内存栅栏和优化 - 通过编译器、抖动和 CPU。

在 x86 上,写入是释放栅栏,这意味着您的后台线程将刷新true对记忆的价值。

所以,您正在寻找的是缓存false循环谓词中的值。编译器或抖动may优化谓词并只评估它一次,但我想它不会在读取类字段时这样做。 CPU不会缓存false价值,因为你正在打电话Console.WriteLine其中包括栅栏。

这段代码需要volatile并且永远不会在没有Volatile.Read:

static void Run()
{
    bool stop = false;

    Task.Factory.StartNew( () => { Thread.Sleep( 1000 ); stop = true; } );

    while ( !stop ) ;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么这个程序在布尔条件变量不存在波动的情况下不会进入无限循环? 的相关文章