Joe Duffy(Windows上的Concurrent Programming的作者)在这篇博客文章中写道,Thread.Sleep(1)比Thread.Sleep(0)更受欢迎,因为它将挂起相同和更低优先级的线程,而不仅仅是与Thread相同的优先级线程.睡眠(0).
在MSDN的.NET版本说是的Thread.Sleep(0)是特殊的,它会暂停这个线程,并允许其他等待线程执行.但它没有提及Thread.Sleep(1)(对于任何.NET版本).
那么,Thread.Sleep(1)实际上做了什么特别的事情吗?
背景:
我正在刷新我对并发编程的了解.我写了一些C#代码,可以明显地显示前/后增量和减量是非原子的,因此不是线程安全的.
为了避免需要创建数百个线程,我在递增共享变量之后放置一个Thread.Sleep(0)以强制调度程序运行另一个线程.这种线程的定期交换使得前/后递增/递减的非原子性质更加明显.
正如预期的那样,Thread.Sleep(0)似乎不会导致额外的延迟.但是,如果我将其更改为Thread.Sleep(1),它似乎恢复到正常的睡眠行为(例如,我大约至少延迟1ms).
这意味着虽然Thread.Sleep(1)可能是首选,但在循环中使用它的任何代码都会运行得慢得多.
这个问题"有人可以用Sleep(1)解释这个有趣的行为吗?" 有点相关,但它是以C++为重点,只是重复Joe Duffy的博客文章中的指导.
这是我感兴趣的任何人的代码(从LinqPad复制,所以你可能需要在它周围添加一个类):
int x = 0;
void Main()
{
List<Thread> threadList=new List<Thread>();
Stopwatch sw=new Stopwatch();
for(int i=0; i<20; i++)
{
threadList.Add(new Thread(Go));
threadList[i].Priority=ThreadPriority.Lowest;
}
sw.Start();
foreach (Thread thread in threadList)
{
thread.Start();
}
foreach (Thread thread in threadList)
{
thread.Join();
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
Thread.Sleep(200);
Console.WriteLine(x);
}
void Go()
{
for(int i=0;i<10000;i++)
{
x++;
Thread.Sleep(0);
}
}
Run Code Online (Sandbox Code Playgroud)