首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >长期等待的C# SpinWait

长期等待的C# SpinWait
EN

Stack Overflow用户
提问于 2016-04-14 09:00:53
回答 1查看 1.7K关注 0票数 10

此代码消耗近零CPU (i5系列)。

代码语言:javascript
复制
    public void SpinWait() {

        for (int i = 0; i < 10000; i++)
        {
            Task.Factory.StartNew(() =>
            {
                var sw = new SpinWait();
                while (true)
                {
                    sw.SpinOnce();
                }
            });
        }
    }

在我的代码中,当旋转是正确的(5次Mops)时,与SemaphoreSlim相比,性能差异是3倍或更多。然而,我担心的是长期使用它.标准的建议是实施两阶段等待操作。我可以检查NextSpinWillYield属性,并引入一个counter+reset来增加默认的自旋迭代,而不是退回到信号量。

但是,仅仅使用SpinWait.SpinOnce来长期等待有什么坏处呢?我已经看过了它的实现,它在需要时会适当地产生效果。它使用的是Thread.SpinWait,在现代CPU上使用暂停指令,根据英特尔的说法是非常有效的。

我在监视Task时发现的一个问题是,如果由于默认的ThreadPool算法而逐渐增加线程数(在所有任务繁忙时,它每秒钟添加一个线程)。这可以通过使用ThreadPool.SetMaxThreads来解决,然后线程数是固定的,并且CPU的使用率仍然接近于零。

如果长期等待任务的数量是有限的,那么使用SpinWait.SpinOnce进行长期等待的其他缺陷是什么。它依赖于CPU家族,操作系统,.NET版本吗?

(为了澄清:我仍然会实现两阶段等待,我只是好奇,为什么不一直使用SpinOnce呢?)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-04-14 10:37:39

好的,反面就是你看到的,你的代码占据了一个线程而没有完成任何事情。防止其他代码运行,并迫使线程池管理器对其进行处理。修补ThreadPool.SetMaxThreads()只是一种绷带,它很可能是大量出血的伤口,只有当你需要赶上飞机回家时才使用它。

只有在您很好地保证这样做比线程上下文切换更有效的时,才应该尝试旋转。这意味着您必须确保线程可以在大约10,000个cpu周期内或更短的时间内继续。这仅仅是5微秒,给予或接受,比大多数程序员所认为的“长期”要少得多。

使用将触发线程上下文切换的同步对象。或者lock关键字。

这不仅会产生处理器,使其他等待线程能够完成它们的工作,从而完成更多的工作,而且它还为OS线程调度程序提供了一个极好的提示。发出信号的同步对象将提高线程的优先级,因此很可能下一个得到处理器。

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36618304

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档