.net - SwitchToThread/Thread.Yield 与 Thread.Sleep(0) 与 Thread.Sleep(1)

标签 .net multithreading concurrency

我正在尝试编写最终的“Yield”方法来将当前时间片交给其他线程。到目前为止,我发现有几种不同的方法可以使线程产生其分配的时间片。我只是想确保我正确地解释了它们,因为文档不是很清楚。因此,根据我在 stackoverflow、MSDN 和各种博客文章上阅读的内容,存在以下选项,它们都有不同的优点/缺点:

SwitchToThread [win32]/Thread.Yield [.NET 4 Beta 1]:屈服于任何同一处理器上的线程

  • 优点:大约快两倍 Thread.Sleep(0)
  • 缺点:仅产生线程 在同一处理器上

Thread.Sleep(0):屈服于任何处理器上具有相同或更高优先级的任何线程

  • 优点:比 Thread.Sleep(1)
  • 缺点:仅产生线程 具有相同或更高优先级

Thread.Sleep(1):屈服于任何处理器上的任何线程

  • 优点:屈服于任何线程 任何处理器
  • 缺点:最慢的选择 (Thread.Sleep(1) 通常会 如果出现以下情况,则将线程挂起大约 15 毫秒 timeBeginPeriod/timeEndPeriod [win32] 未使用)

Thread.SpinWait怎么样?它可以用于产生线程的时间片吗?如果不是的话,它有什么用?

我还有一些遗漏或错误解释的内容。如果您能纠正/补充我的理解,我将不胜感激。

到目前为止,这是我的 Yield 方法的样子:

public static class Thread
{
    [DllImport("kernel32.dll")]
    static extern bool SwitchToThread();

    [DllImport("winmm.dll")]
    internal static extern uint timeBeginPeriod(uint period);

    [DllImport("winmm.dll")]
    internal static extern uint timeEndPeriod(uint period);

    /// <summary>  yields time slice of current thread to specified target threads </summary>
    public static void YieldTo(ThreadYieldTarget threadYieldTarget)
    {
        switch (threadYieldTarget) {
            case ThreadYieldTarget.None: 
                break; 
            case ThreadYieldTarget.AnyThreadOnAnyProcessor:
                timeBeginPeriod(1); //reduce sleep to actually 1ms instead of system time slice with is around 15ms
                System.Threading.Thread.Sleep(1); 
                timeEndPeriod(1); //undo
                break;
            case ThreadYieldTarget.SameOrHigherPriorityThreadOnAnyProcessor:
                System.Threading.Thread.Sleep(0); 
                break;
            case ThreadYieldTarget.AnyThreadOnSameProcessor:
                SwitchToThread();
                break;
            default: throw new ArgumentOutOfRangeException("threadYieldTarget");
        }
    }
}

public enum ThreadYieldTarget
{
    /// <summary>  Operation system will decide when to interrupt the thread </summary>
    None,
    /// <summary>  Yield time slice to any other thread on any processor </summary>
    AnyThreadOnAnyProcessor,
    /// <summary>  Yield time slice to other thread of same or higher piority on any processor </summary>
    SameOrHigherPriorityThreadOnAnyProcessor,
    /// <summary> Yield time slice to any other thread on same processor </summary>
    AnyThreadOnSameProcessor
}

最佳答案

SpinWait 在超线程处理器上很有用。通过超线程,多个操作系统调度的线程可以在同一物理处理器上运行,共享处理器资源。 SpinWait 向处理器表明您没有做任何有用的工作,它应该运行来自不同逻辑 CPU 的代码。顾名思义,它通常在旋转时使用。

假设您有如下代码:

while (!foo) {} // Spin until foo is set.

如果该线程在超线程处理器上的线程上运行,则它会消耗可用于该处理器上运行的其他线程的处理器资源。

更改为:

while (!foo) {Thread.SpinWait(1);} 

我们正在指示 CPU 向其他线程提供一些资源。

SpinWait 不影响操作系统的线程调度。

对于您关于“最终产量”的主要问题,这在很大程度上取决于您的情况 - 如果不澄清为什么您希望线程屈服,您将无法获得好的答案。从我的角度来看,让出处理器的最佳方法是让线程进入等待状态,并且仅在有工作要做时才唤醒。其他任何事情都只是浪费 CPU 时间。

关于.net - SwitchToThread/Thread.Yield 与 Thread.Sleep(0) 与 Thread.Sleep(1),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1413630/

相关文章:

javascript -\r\n CSV 文件中的字符未被视为换行符

.net - "Type"在物理上是什么意思?

java - 我会在这里同步什么?

Spring框架MVC "concurrency"?

python - Concurrent.futures : what are the use cases for map() vs. 提交()?

.net - EF 的自定义实体命名规则

c# - 为什么我在打开连接时收到 "Invalid attempt to call HasRows when reader is closed"?

java - 使用Java线程池,如何根据消息特性串行处理某些消息,并行处理其他消息?

c - C是单线程语言吗

multithreading - 编译器优化破坏多线程代码