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

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.

主站蜘蛛池模板: 南部县| 金平| 酉阳| 松滋市| 于都县| 绥宁县| 荔浦县| 高要市| 钟祥市| 迁西县| 西宁市| 安丘市| 许昌市| 旬阳县| 江达县| 西乡县| 镇远县| 登封市| 黑山县| 周口市| 万宁市| 容城县| 新绛县| 扎兰屯市| 泰和县| 连山| 佛山市| 泾阳县| 岗巴县| 望城县| 丰宁| 禄劝| 墨竹工卡县| 皮山县| 罗定市| 和龙市| 珠海市| 涟源市| 双鸭山市| 泽普县| 万载县|