c# - 在标志字段上使用 volatile 关键字

标签 c# multithreading volatile

我尝试了解 volatile 在多线程上下文中的使用。在以下代码中 another source of knowledge在互联网上:

class Program
{
    static string _result;
    //static volatile bool _done;
    static bool _done;

    static void SetVolatile()
    {
        // Set the string.
        _result = "Dot Net Perls";
        // The volatile field must be set at the end of this method.
        _done = true;
    }

    static void Main()
    {
        // Run the above method on a new thread.
        new Thread(new ThreadStart(SetVolatile)).Start();

        // Wait a while.
        Thread.Sleep(200);

        // Read the volatile field.
        if (_done)
        {
            Console.WriteLine(_result);
        }
    }
}

volatile 关键字的演示使用应防止线程读取存储在缓存中的值。相反,它应该检查实际值。

因此,如果没有 volatile 的 _done ,仍然应该有一个 false 值(从缓存中读取),并且 Console.WriteLine 语句不应被执行。

不幸的是,在调试/ Release模式下运行此代码而不使用 volatile 关键字总是会产生输出。这个特定示例的要点是什么?

最佳答案

正如已经说过的,不使用 volatile 关键字并不意味着在所有情况下所有读取都需要缓存。它们可能被缓存,也可能没有。但如果您想要更多可重现的示例,请尝试以下操作:

class Program {
    static string _result;
    //static volatile bool _done;
    static bool _done;
    static void SetVolatile() {
        // Set the string.
        _result = "Dot Net Perls";
        // The volatile field must be set at the end of this method.
        _done = true;
    }

    static void Main() {
        // Run the above method on a new thread.
        new Thread(new ThreadStart(SetVolatile)).Start();

        // prevent compiler to throw away empty while loop
        // by doing something in it
        int i = 0;
        while (!_done) {
            i++;
        }
        Console.WriteLine("done " + i);
    }
}

在这里,您在 while 循环中重复读取 _done ,增加了它被缓存的可能性。程序应该以“done”消息终止,但不会,因为从另一个线程对 _done 的更改不会被注意到。

关于c# - 在标志字段上使用 volatile 关键字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47309012/

相关文章:

java - Java如何将数组拆分为多个线程

c++ - 为什么 UI 更改在 Qt 中不是即时的?

java - 同步对 Volatile 字段的写入访问(廉价读写 block )

c# - 在没有先验消息类型知识的情况下解析 HL7

c# - 如何在 Linq 中获得 SUM?

multithreading - Delphi异常处理,使用E : Exception or ExceptObject

java - ConcurrentHashMap 作为具有同步的单例缓存

c++ - 一线程读一线程写,std::deque安全吗?

c# - 使用 PanGestureRecognizer 的 Xamarin.Forms - 在 UWP 上移出窗口区域不会触发状态已取消或已完成

c# - 字段是可序列化类型的成员,但属于不可序列化类型