官术网_书友最值得收藏!

Using the SpinWait construct

This recipe will describe how to wait on a thread without involving kernel-mode constructs. In addition, we introduce SpinWait, a hybrid synchronization construct designed to wait in the user mode for some time, and then switch to the kernel mode to save CPU time.

Getting ready

To step through this recipe, you will need Visual Studio 2015. There are no other prerequisites. The source code for this recipe can be found at BookSamples\Chapter2\Recipe9.

How to do it...

To understand how to wait on a thread without involving kernel-mode constructs, perform the following steps:

  1. Start Visual Studio 2015. Create a new C# console application project.
  2. In the Program.cs file, add the following using directives:
    using System;
    using System.Threading;
    using static System.Console;
    using static System.Threading.Thread;
  3. Below the Main method, add the following code:
    static volatile bool _isCompleted = false;
    
    static void UserModeWait()
    {
      while (!_isCompleted)
      {
        Write(".");
      }
      WriteLine();
      WriteLine("Waiting is complete");
    }
    
    static void HybridSpinWait()
    {
      var w = new SpinWait();
      while (!_isCompleted)
      {
        w.SpinOnce();
        WriteLine(w.NextSpinWillYield);
      }
      WriteLine("Waiting is complete");
    }
  4. Inside the Main method, add the following code:
    var t1 = new Thread(UserModeWait);
    var t2 = new Thread(HybridSpinWait);
    
    WriteLine("Running user mode waiting");
    t1.Start();
    Sleep(20);
    _isCompleted = true;
    Sleep(TimeSpan.FromSeconds(1));
    _isCompleted = false;
    WriteLine("Running hybrid SpinWait construct waiting");
    t2.Start();
    Sleep(5);
    _isCompleted = true;
  5. Run the program.

How it works...

When the main program starts, it defines a thread that will execute an endless loop for 20 milliseconds until the main thread sets the _isCompleted variable to true. We could experiment and run this cycle for 20-30 seconds instead, measuring the CPU load with the Windows task manager. It will show a significant amount of processor time, depending on how many cores the CPU has.

We use the volatile keyword to declare the _isCompleted static field. The volatile keyword indicates that a field might be modified by multiple threads being executed at the same time. Fields that are declared volatile are not subject to compiler and processor optimizations that assume access by a single thread. This ensures that the most up-to-date value is present in the field at all times.

Then, we use a SpinWait version, which on each iteration prints a special flag that shows us whether a thread is going to switch to a blocked state. We run this thread for 5 milliseconds to see that. In the beginning, SpinWait tries to stay in the user mode, and after about nine iterations, it begins to switch the thread to a blocked state. If we try to measure the CPU load with this version, we will not see any CPU usage in the Windows task manager.

主站蜘蛛池模板: 屏边| 六枝特区| 慈利县| 新邵县| 北流市| 昌宁县| 延寿县| 六安市| 马鞍山市| 梁平县| 阿图什市| 隆林| 汉沽区| 东源县| 张北县| 东方市| 西贡区| 杭锦后旗| 洪江市| 德昌县| 鹰潭市| 博罗县| 旺苍县| 清苑县| 峡江县| 青川县| 太湖县| 西宁市| 全南县| 连城县| 盐城市| 新闻| 徐闻县| 四子王旗| 自贡市| 交口县| 天等县| 班戈县| 五原县| 云霄县| 石景山区|