• C# 特性之volatile


    C# 2.0特性:Volatile

    volatile 关键字指示一个字段可以由多个同时执行的线程修改。 出于性能原因,编译器,运行时系统甚至硬件都可能重新排列对存储器位置的读取和写入。 声明了 volatile 的字段不进行这些优化。 添加 volatile 修饰符可确保所有线程观察易失性写入操作(由任何其他线程执行)时的观察顺序与写入操作的执行顺序一致。 不确保从所有执行线程整体来看时所有易失性写入操作均按执行顺序排序。

    volatile 关键字可应用于以下类型的字段:

    • 引用类型。
    • 指针类型(在不安全的上下文中)。 请注意,虽然指针本身可以是可变的,但是它指向的对象不能是可变的。 换句话说,不能声明“指向可变对象的指针”。
    • 简单类型,如 sbytebyteshortushortintuintcharfloat 和 bool
    • 具有以下基本类型之一的 enum 类型:bytesbyteshortushortint 或 uint
    • 已知为引用类型的泛型类型参数。
    • IntPtr 和 UIntPtr

    其他类型(包括 double 和 long)无法标记为 volatile,因为对这些类型的字段的读取和写入不能保证是原子的。 若要保护对这些类型字段的多线程访问,请使用 Interlocked 类成员或使用 lock 语句保护访问权限。

    volatile 关键字只能应用于 class 或 struct 的字段。 不能将局部变量声明为 volatile

     

    下面的示例说明如何将公共字段变量声明为 volatile

    class VolatileTest
    {
        public volatile int sharedStorage;
    
        public void Test(int _i)
        {
            sharedStorage = _i;
        }
    }

    下面的示例演示如何创建辅助线程,并用它与主线程并行执行处理。

     1 public class Worker
     2 {
     3     // This method is called when the thread is started.
     4     public void DoWork()
     5     {
     6         bool work = false;
     7         while (!_shouldStop)
     8         {
     9             work = !work; // simulate some work
    10         }
    11         Console.WriteLine("Worker thread: terminating gracefully.");
    12     }
    13     public void RequestStop()
    14     {
    15         _shouldStop = true;
    16     }
    17     // Keyword volatile is used as a hint to the compiler that this data
    18     // member is accessed by multiple threads.
    19     private volatile bool _shouldStop;
    20 }
    21 
    22 public class WorkerThreadExample
    23 {
    24     public static void Main()
    25     {
    26         // Create the worker thread object. This does not start the thread.
    27         Worker workerObject = new Worker();
    28         Thread workerThread = new Thread(workerObject.DoWork);
    29 
    30         // Start the worker thread.
    31         workerThread.Start();
    32         Console.WriteLine("Main thread: starting worker thread...");
    33 
    34         // Loop until the worker thread activates.
    35         while (!workerThread.IsAlive)
    36             ;
    37 
    38         // Put the main thread to sleep for 500 milliseconds to
    39         // allow the worker thread to do some work.
    40         Thread.Sleep(500);
    41 
    42         // Request that the worker thread stop itself.
    43         workerObject.RequestStop();
    44 
    45         // Use the Thread.Join method to block the current thread 
    46         // until the object's thread terminates.
    47         workerThread.Join();
    48         Console.WriteLine("Main thread: worker thread has terminated.");
    49     }
    50     // Sample output:
    51     // Main thread: starting worker thread...
    52     // Worker thread: terminating gracefully.
    53     // Main thread: worker thread has terminated.
    54 }

    将 volatile 修饰符添加到 _shouldStop 的声明后,将始终获得相同的结果(类似于前面代码中显示的片段)。 但是,如果 _shouldStop 成员上没有该修饰符,则行为是不可预测的。 DoWork 方法可能会优化成员访问,从而导致读取陈旧数据。 鉴于多线程编程的性质,读取陈旧数据的次数是不可预测的。 不同的程序运行会产生一些不同的结果。

  • 相关阅读:
    meta标签设置(移动端)
    清除浮动
    响应式设计
    堆和堆排序
    O(n^2)以及O(nlogn)时间复杂度的排序算法
    求数组的最大连续子数组和
    HTTP缓存原理
    将两个有序数组合并为一个有序数组
    如何实现居中对齐
    查找字符串中出现最多的字符
  • 原文地址:https://www.cnblogs.com/aisa-thanatos/p/10984376.html
Copyright © 2020-2023  润新知