SpinWait封装常见旋转逻辑。在单处理器计算机上,始终使用 “生成” 而不是 “繁忙等待”,在装有超线程技术的 Intel 处理器的计算机上,这有助于防止硬件线程不足。SpinWait 封装了一种很好的旋转和真正的生成。

SpinWait是一个值类型,这意味着低级别代码可以使用 SpinWait,而不必担心不必要的分配开销。SpinWait 对于普通应用程序通常不起作用。在大多数情况下,应使用由 .NET Framework 提供的同步类,如 Monitor 。但在需要自旋等待的大多数情况下, SpinWait 类型应优先于 Thread.SpinWait 方法。

System.Threading.SpinWait 是一种轻型同步类型,可用于低级方案,以避免执行内核事件所需的高成本上下文切换和内核转换。在多核计算机上,如果不得长时间保留资源,更高效的做法是,先让等待线程在用户模式下旋转几十或几百个周期,再重试获取资源。如果资源在旋转后可用,便节省了几千个周期。如果资源仍不可用,那么也只花了几个周期,仍可以进入基于内核的等待。这种“旋转后等待”的组合有时称为“两阶段等待操作” 。

SpinWait 旨在与包装内核事件(如 ManualResetEvent)的 .NET Framework 类型结合使用。SpinWait 本身也可以仅在一个程序中用于提供基本的旋转功能。

SpinWait 不仅仅只是空循环。谨慎实现后,它可以提供适用于一般情况的正确旋转行为,并且本身能够在旋转时间够长(大致是内核转换所需的时间长度)时自行启动上下文切换。例如,在单核计算机上,SpinWait 会立即生成线程的时间片,因为旋转会阻止所有线程取得进展。即使在多核计算机上,SpinWait 也会生成时间片,以防等待线程阻止优先级较高的线程或垃圾回收器。因此,若要在两阶段等待操作中使用 SpinWait,建议在 SpinWait 本身启动上下文切换前,先调用内核等待。SpinWait 提供每次调用 SpinOnce 前都可以检查的 NextSpinWillYield 属性。如果此属性返回 true,启动自己的等待操作。


看完官方说明一脸懵逼,将上面的语言用通俗的话来说,Thread.Sleep方法在执行时,会将阻止的时间的CPU切换至其他等待的进程,等到Thread.Sleep等待时间到后,再获取CPU的控制权继续执行下一步操作;SpinWait提供了While循环方法,在等待通过循环来阻止当前CPU的释放,一直等待当前方法执行完成然后释放。我们都知道进程在切换的时候会有时间与内存的消耗,所以尽可能使用SpinWait替代Thread.Sleep。

现在我们看下SpinWait结构中的代码:

/// <summary>
/// 循环一次
/// </summary>
/// <remarks>
/// This is typically called in a loop, and may change in behavior based on  the number of times a
/// <see cref="SpinOnce"/> has been called thus far on this instance.
/// </remarks>
public void SpinOnce()
{if (NextSpinWillYield){int yieldsSoFar = (m_count >= YIELD_THRESHOLD ? m_count -  YIELD_THRESHOLD : m_count);//③循环到20次时,执行Thread.Sleep(01)if ((yieldsSoFar % SLEEP_1_EVERY_HOW_MANY_TIMES) ==  (SLEEP_1_EVERY_HOW_MANY_TIMES - 1)){//当前线程挂起,让出cpu//所有挂起的线程都有机会竞争当前时间片段,不限制线程优先级Thread.Sleep(1);}//②执行Thread.Yield()5次后,执行Thread.Sleep(0)   else if ((yieldsSoFar % SLEEP_0_EVERY_HOW_MANY_TIMES) ==  (SLEEP_0_EVERY_HOW_MANY_TIMES - 1)){//当前线程挂起,让出cpu//(只允许那些优先级相等或更高的线程使用当前的CPU。//如果没有,那当前线程会重新使用CPU时间片)//(上面已说明,后续补充实现)Thread.Sleep(0);}else{//当前线程挂起(执行状态->就绪状态), 让出cpu,//(后续补充实现逻辑)Thread.Yield();}}else{//线程等待//4,8,16,32,64...位运算,2的n次方//①循环10次Thread.SpinWait(4 << m_count);}// m_count 递增; m_count 达到最大值后回滚Count =10m_count = (m_count == int.MaxValue ? YIELD_THRESHOLD : m_count + 1);
}
/// <summary>
/// 重置循环计数器
/// </summary>
public void Reset()
{m_count = 0;
}
#region Static Methods
/// <summary>
/// 循环.直到condition返回True
/// </summary>
public static void SpinUntil(Func<bool> condition)
{SpinUntil(condition, Timeout.Infinite);
}
/// <summary>
/// 循环,直到condition返回True或者时间达到timeout
/// </summary>
public static bool SpinUntil(Func<bool> condition, TimeSpan timeout)
{//校验时间格式是否正确Int64 totalMilliseconds = (Int64)timeout.TotalMilliseconds;if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue){throw new System.ArgumentOutOfRangeException("timeout", timeout, "SpinWait_SpinUntil_TimeoutWrong");}return SpinUntil(condition, (int)timeout.TotalMilliseconds);
}
/// <summary>
/// 直到condition返回True或者时间达到timeout.
/// </summary>
public static bool SpinUntil(Func<bool> condition, int millisecondsTimeout)
{//校验时间格式if (millisecondsTimeout < Timeout.Infinite){throw new ArgumentOutOfRangeException("millisecondsTimeout", millisecondsTimeout,  "SpinWait_SpinUntil_TimeoutWrong");}//空值校验if (condition == null){throw new ArgumentNullException("condition",  "SpinWait_SpinUntil_ArgumentNull");}uint startTime = 0;if (millisecondsTimeout != 0 && millisecondsTimeout != Timeout.Infinite){//自上次启动计算机以来所经过的时间(以毫秒为单位)。startTime = TimeoutHelper.GetTime();}SpinWait spinner = new SpinWait();while (!condition()){if (millisecondsTimeout == 0){return false;}spinner.SpinOnce();//计时if (millisecondsTimeout != Timeout.Infinite &&  spinner.NextSpinWillYield){if (millisecondsTimeout <= (TimeoutHelper.GetTime() - startTime)){return false;}}}return true;
}
#endregion

C#番外篇-SpinWait相关推荐

  1. [zt]数学之美番外篇:平凡而又神奇的贝叶斯方法

    数学之美番外篇:平凡而又神奇的贝叶斯方法 Tags: 数学, 机器学习与人工智能, 计算机科学 save it69 saved tags: 贝叶斯 math bayesian algorithm 数学 ...

  2. 『中级篇』docker之wordpress容器SSL(番外篇)(78)

    原创文章,欢迎转载.转载请注明:转载自IT人故事会,谢谢! 原文链接地址:『中级篇』docker之wordpress容器SSL(番外篇)(78) 搞了2天终于搞定了,现在分享给大家. apache2 ...

  3. 『中级篇』docker之虚拟机创建vagrant技巧(番外篇)(81)

    原创文章,欢迎转载.转载请注明:转载自IT人故事会,谢谢! 原文链接地址:『中级篇』docker之虚拟机创建vagrant技巧(番外篇)(81) 之前一直用的原生的centos7的源镜像安装虚拟机,然 ...

  4. yxy和志愿者小姐姐番外篇之大宝宝123追番记(补题,淘汰赛)

    1264: yxy和志愿者小姐姐番外篇之大宝宝123追番记 时间限制: 1 Sec  内存限制: 64 MB                                               ...

  5. 转:数学之美番外篇:平凡而又神奇的贝叶斯方法 收藏

    为什么80%的码农都做不了架构师?>>>    转自:http://blog.csdn.net/pongba/archive/2008/09/21/2958094.aspx 数学之美 ...

  6. 教你从0到1搭建秒杀系统-Canal快速入门(番外篇)

    Canal用途很广,并且上手非常简单,小伙伴们在平时完成公司的需求时,很有可能会用到.本篇介绍一下数据库中间件Canal的使用. 很多时候为了缩短调用延时,我们会对部分接口数据加入了缓存.一旦这些数据 ...

  7. 文本分类入门(番外篇)特征选择与特征权重计算的区别

    文本分类入门(番外篇)特征选择与特征权重计算的区别 在文本分类的过程中,特征(也可以简单的理解为"词")从人类能够理解的形式转换为计算机能够理解的形式时,实际上经过了两步骤的量化- ...

  8. 5年前面试题引发的“血案”(番外篇)(总结和乱侃)

    这货是说好的番外篇-- 所谓的番外篇其实就是对前面的各个知识点做一些总结. 血案(1)中的两个内容主要是日志切换时的检查点和表空间管理. 日志切换其实远远没有简单,有关于检查点和日志文件的内容太多了, ...

  9. Java微信公众平台开发--番外篇,对GlobalConstants文件的补充

    转自:http://www.cuiyongzhi.com/post/63.html 之前发过一个[微信开发]系列性的文章,也引来了不少朋友观看和点评交流,可能我在写文章时有所疏忽,对部分文件给出的不是 ...

  10. PostCSS自学笔记(二)【番外篇二】

    图解PostCSS的插件执行顺序 文章其实是一系列的早就写完了. 才发现忘了发在SegmentFault上面, 最早发布于https://gitee.com/janking/Inf... 这次我继续研 ...

最新文章

  1. mysql 数据范围总结
  2. python语言if语句-python的if语句
  3. 人类史上最大最好的希望事件
  4. twitter storm源码走读(五)
  5. E1 PCM复用设备能当程控交换机用吗?
  6. python读取mysql数据_Selenium(Python) ddt读取MySQL数据驱动
  7. 干货 | 数据分析的 7 个关键步骤是什么?
  8. 没有bug队——加贝——Python 51,52
  9. 数据结构 (一) ----- 数据结构基本概念基于数组实现线性表
  10. 华为一则面试题登上热搜;大众点评会员因点赞过多被处罚;Linux Kernel 5.12 发布|极客头条...
  11. C++学生信息管理系统1.0
  12. 小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_5-9.使用JWT生成用户Token回写客户端...
  13. 微软更新服务器ip地址,微软承认Windows 10更新导致路由等本地IP地址打不开
  14. python数据挖掘学习路线图
  15. python3网络爬虫(堆糖网)
  16. 人工智能研究中心快递柜——代码分析五
  17. 让Meebo自动变换背景的客户端脚本
  18. python禁用路径长度限制有啥影响吗_为什么Windows中存在260个字符的路径长度限制?...
  19. HDU 4489(DP)
  20. 基于深度摄像头的障碍物检测(realsense+opencv)

热门文章

  1. 基于UP30飞控系统的无人机地面站航线规划方法
  2. 摄影测量(一):概述
  3. 各个版本的精易模块分享下载
  4. 嵌入式linux usb联网,嵌入式linux下MF825C上网
  5. python单例模式selenium driver实现单例
  6. 软考-中级-网络工程师-知识点个人总结(二)
  7. PDM系统服务器管理,PDM产品数据管理系统
  8. maven配置阿里镜像
  9. 数据优化——分库分表(三)中间件讲解
  10. Android 自动点击工具,安卓自动点击器免费版