我正在尝试编写最终的“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/