博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SpinWait的性能高于Thread.Sleep
阅读量:2435 次
发布时间:2019-05-10

本文共 2043 字,大约阅读时间需要 6 分钟。

在进行多线程开发时,我们经常会用到Thread.Sleep(timeout_ms)来等待或者腾出时间来让其他线程处理。不过,即使我们把timeout_ms设置为0,Thread.Sleep还是会执行等待操作。这就让人很纳闷了,我明明指定的等待时间是0毫秒,为什么还会执行等待呢?

这时因为当我们调用Thread.Sleep时,是让内核暂停处理当前的线程,然后再看需要等待多久,当发现等待时间是timeout_ms时,就等待timeout_ms长的时间,然后内核继续运行该线程。即使timeout_ms为0,由于这个过程中内核已经执行了暂停和恢复的动作,所以会消耗时间。这样也就说明了,即时Thread.Sleep等待的时候是0,还是会有等待的过程。

而如果使用自旋等待就会不一样。下面先看一下代码和执行结果。

[csharp]
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Diagnostics;  
  4. using System.Linq;  
  5. using System.Text;  
  6. using System.Threading;  
  7.   
  8. namespace SpinWaitTest  
  9. {  
  10.     class Program  
  11.     {  
  12.         private static int _count = 1000;  
  13.         private static int _timeout_ms = 10;  
  14.   
  15.         static void Main(string[] args)  
  16.         {  
  17.             //NoSleep();  
  18.             ThreadSleepInThread();  
  19.             SpinWaitInThread();  
  20.             Console.ReadLine();  
  21.         }  
  22.   
  23.         private static void NoSleep()  
  24.         {  
  25.             Thread thread = new Thread(() =>  
  26.             {  
  27.                 var sw = Stopwatch.StartNew();  
  28.                 for (int i = 0; i < _count; i++)  
  29.                 {  
  30.                      
  31.                 }  
  32.                 Console.WriteLine("No Sleep Consume Time:{0}", sw.Elapsed.ToString());  
  33.             });  
  34.             thread.IsBackground = true;  
  35.             thread.Start();  
  36.         }  
  37.   
  38.         private static void ThreadSleepInThread()  
  39.         {  
  40.             Thread thread = new Thread(() =>  
  41.             {  
  42.                 var sw = Stopwatch.StartNew();  
  43.                 for (int i = 0; i < _count; i++)  
  44.                 {  
  45.                     Thread.Sleep(_timeout_ms);  
  46.                 }  
  47.                 Console.WriteLine("Thread Sleep Consume Time:{0}", sw.Elapsed.ToString());  
  48.             });  
  49.             thread.IsBackground = true;  
  50.             thread.Start();  
  51.         }  
  52.   
  53.         private static void SpinWaitInThread()  
  54.         {  
  55.             Thread thread = new Thread(() =>  
  56.             {  
  57.                 var sw = Stopwatch.StartNew();  
  58.                 for (int i = 0; i < _count; i++)  
  59.                 {  
  60.                     SpinWait.SpinUntil(() => true, _timeout_ms);  
  61.                 }  
  62.                 Console.WriteLine("SpinWait Consume Time:{0}", sw.Elapsed.ToString());  
  63.             });  
  64.             thread.IsBackground = true;  
  65.             thread.Start();  
  66.         }  
  67.     }  
  68. }  
运行结果

看看结果会发现,Thread.Sleep的时间比SpinWait多了近50万倍,这相差实在是太大了。有人会说了,Thread.Sleep是执行了10ms*1000=10s的等待,而SpinWait.SpinUntil的条件直接是true,所以相当于没有等待,时间自然会少了很多。那好,我们把_timeout_ms设成0,然后再看运行结果。

我们看到Thread.Sleep的等待时间还是要比SpinWait的长了近10倍,这是为什么呢?

这是因为SpinWait.SpinUntil在执行等待时,会先进行自旋。所谓自旋就是在CPU运转的周期内,如果条件满足了,就不会再进入内核等待(即暂停该线程,等待一段时间后,再继续运行该线程),如果条件不满足,才进入内核等待。这样一来,SpinWait会比Thread.Sleep多运行一次的CPU周期,再进入等待。因为CPU周期是很短的(现在一般的电脑都有2.1GHZ以上),所以这个等待对时间影响不大,却可以提升很大的性能。

可以参看MSDN的说明

你可能感兴趣的文章
如何建立C++ BuilderX 1.5 Mobile Edition开发环境(转)
查看>>
蓝牙套接字概述(转)
查看>>
TCPDUMP简介(转)
查看>>
Symbian智能手机特殊号码搜集(转)
查看>>
Linux操作系统下媒体播放器的初步探讨(转)
查看>>
网站内页权重如何提高-SEO优化技术群课堂笔记(转)
查看>>
用MSDOS.SYS同装两个WIN98(转)
查看>>
用DHTML来模拟实现下拉菜单(转)
查看>>
oracle数据库应用中实现汉字“同音”查询(转)
查看>>
关于无盘网络正确网络配置建议,减少卡机蓝屏关键(转)
查看>>
交换机及路由器如何才能更加安全?(转)
查看>>
chinaunix
查看>>
bxp读写分离怎么设置(转)
查看>>
复制表结构的通用存储过程(转)
查看>>
Symbian OS SDKs简介(转)
查看>>
[组图]基于Nokia S60的游戏开发之四(转)
查看>>
屡次选错终致项目暴毙(转)
查看>>
WinXP优化 全面消除操作系统的复制乱码(转)
查看>>
symbian 60 开发的一个问题-让左右键都能弹出菜单(转)
查看>>
SQL Server静态页面导出技术(转)
查看>>