c# - Thread.Sleep(1) 有什么特别之处吗?

标签 c# multithreading

Joe Duffy(Concurrent Programming on Windows 的作者)在 this blog article 中写道Thread.Sleep(1) 优于 Thread.Sleep(0),因为它会挂起相同和较低优先级的线程,而不仅仅是与 Thread.Sleep(0) 相同优先级的线程。

.NET version of MSDN says Thread.Sleep(0) 比较特殊,它会挂起这个线程,让其他等待的线程执行。但它没有提及 Thread.Sleep(1)(对于任何 .NET 版本)。

那么,Thread.Sleep(1) 实际上做了什么特别的事情吗?

背景:

我正在更新并发编程方面的知识。我写了一些 C# 代码来明显地表明前/后递增和递减是非原子的,因此不是线程安全的。

为了避免需要创建数百个线程,我在递增共享变量后放置了一个 Thread.Sleep(0) 以强制调度程序运行另一个线程。这种线程的定期交换使得前/后递增/递减的非原子性质更加明显。

Thread.Sleep(0) 似乎不会像预期的那样导致额外的延迟。但是,如果我将其更改为 Thread.Sleep(1),它似乎会恢复正常的 sleep 行为(例如,我得到大约至少 1 毫秒的延迟)。

这意味着虽然 Thread.Sleep(1) 可能是首选,但在循环中使用它的任何代码都会运行得慢得多。

这个问题"Could someone explain this interesting behaviour with 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);
    }
}

最佳答案

您不再需要使用 Sleep(1) 而不是 Sleep(0) 因为 Microsoft 更改了 Windows API Sleep().

来自 the MSDN documentation for Sleep() ,这就是 Sleep(0) 现在发生的情况:

A value of zero causes the thread to relinquish the remainder of its time slice to any other thread that is ready to run. If there are no other threads ready to run, the function returns immediately, and the thread continues execution.

这是在 Windows XP 中经常发生的事情:

A value of zero causes the thread to relinquish the remainder of its time slice to any other thread of equal priority that is ready to run. If there are no other threads of equal priority ready to run, the function returns immediately, and the thread continues execution. This behavior changed starting with Windows Server 2003.

注意“任何其他线程”和“任何其他具有同等优先级的线程”之间的区别。

Joe Duffy 建议使用 Sleep(1) 而不是 Sleep(0) 的唯一原因是因为它是最短的 Sleep() 值,可以防止 Sleep() 在没有其他线程时立即返回 在 Windows XP 上运行时具有同等优先级准备运行。

对于 Windows Server 2003 之后的操作系统版本,您无需担心这一点,因为 Sleep() 的行为发生了变化。

我提请您注意 Joe 博客的这一部分:

And even though there's an explicit Sleep in there, issuing it doesn't allow the producer to be scheduled because it's at a lower priority.

在 XP 中,即使主线程(具有较高优先级)执行 Sleep(0),较低优先级线程也会处于饥饿状态。在 XP 之后,这将不再发生,因为 Sleep(0) 将允许较低优先级的线程运行。

关于c# - Thread.Sleep(1) 有什么特别之处吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16584358/

相关文章:

c# - 为什么电话数据注释不起作用,即使在需要时也是如此?

c# - 为什么我需要协方差接口(interface)(输出类型)?

c# - 如何强制项目/解决方案以管理员权限在 Visual Studio 中打开?

c# - 为什么使用C++而不是C#来进行驱动级编程(系统级编程)

c# - 需要帮助跨 UI 线程和 C# 中的另一个线程获取信息

多线程和多进程的Java文件锁定方式

c - 线程工作不当

vb.net - 多线程的最佳方式

c# - 如何使用 Open Text Summarizer API?

java - 常见 io copyUrlToFile 不起作用