38 .net concurrency multithreading
我正在尝试编写最终的"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)如果
不使用timeBeginPeriod/ timeEndPeriod[win32],通常会将线程暂停约15ms
)怎么样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
}
Run Code Online (Sandbox Code Playgroud)
Mic*_*ael 12
SpinWait在超线程处理器上很有用.通过超线程,多个OS调度线程可以在同一物理处理器上运行,共享处理器资源.SpinWait向处理器指示您没有做任何有用的工作,并且它应该从不同的逻辑CPU运行代码.顾名思义,它通常在您旋转时使用.
假设您有以下代码:
while (!foo) {} // Spin until foo is set.
Run Code Online (Sandbox Code Playgroud)
如果此线程在超线程处理器上的线程上运行,则会消耗可用于处理器上运行的其他线程的处理器资源.
通过更改为:
while (!foo) {Thread.SpinWait(1);}
Run Code Online (Sandbox Code Playgroud)
我们指示CPU为其他线程提供一些资源.
SpinWait不会影响线程的OS调度.
对于关于"终极收益"的主要问题,它在很大程度上取决于您的情况 - 如果没有说明您希望线程产生的原因,您将无法得到一个好的答案.从我的角度来看,产生处理器的最好方法是让线程进入等待状态,只有在有工作要做时才会醒来.其他任何东西只是在浪费CPU时间.
SpinWait 被设计为等待而不产生当前时间片
它是为这样的情况而设计的:您知道自己想要在很短的时间内完成某件事,因此失去时间片将是过多的。
我的印象是 Thread.Yield(x) 对于 x < 线程量子的任何值都是等效的,包括零,尽管我没有这方面的基准。
Jeff Moser撰写的文章" Hows Locks Lock"(http://www.moserware.com/2008/09/how-do-locks-lock.html)可以给出一些关于SpinWait机制的内容.引用该文件:
到底是做什么的?看看Rotor的clr/src/vm/comsynchronizable.cpp给了我们现实:
FCIMPL1(void,ThreadNative :: SpinWait,int iterations){WRAPPER_CONTRACT; STATIC_CONTRACT_SO_TOLERANT;
Run Code Online (Sandbox Code Playgroud)for(int i = 0; i < iterations; i++) YieldProcessor();} FCIMPLEND
进一步的潜水表明"YieldProcessor"是这个宏:
#define YieldProcessor()__ asm {rep nop}
这是一个"重复无操作"汇编指令.它在英特尔指令集手册中也称为"PAUSE - Spin Loop Hint".这意味着CPU知道我们想要完成的旋转等待.
相关:http : //msdn.microsoft.com/en-us/library/ms687419(VS85).aspx http://www.moserware.com/2008/09/how-do-locks-lock.html# lockfn7
| 归档时间: |
|
| 查看次数: |
13204 次 |
| 最近记录: |