【问题标题】:Why Thread.Sleep(0) time-slice handled over threads with lower priorities?为什么 Thread.Sleep(0) 时间片处理优先级较低的线程?
【发布时间】:2018-02-23 07:05:02
【问题描述】:

据我所知,Thread.Sleep(0) 仅将时间片提供给具有相同或更高优先级的另一个线程。 我做了一些测试应用:

class Program
{
    public static void ThreadMethod()
    {
        for (int i = 0; i < 300; i++)
        {
            Thread.Sleep(0);
            Console.WriteLine("{0} ThreadProc: {1}, prio {2} ", Thread.CurrentThread.ManagedThreadId,
                i, Thread.CurrentThread.Priority);
        }
    }

    public static void Main()
    {
        Thread.CurrentThread.Priority = ThreadPriority.Normal;
        Thread t = new Thread(new ThreadStart(ThreadMethod));
        t.Priority = ThreadPriority.Highest;

        Thread t2 = new Thread(new ThreadStart(ThreadMethod));
        t2.Priority = ThreadPriority.Lowest;

        Process.GetCurrentProcess().ProcessorAffinity = (System.IntPtr)1;

        t.Start();
        t2.Start();

        t2.Join();
        t.Join();
    }
}

这是模拟单核CPU,据我所知,这里应该只执行最高优先级的线程,但我看到的是: 低优先级线程每次操作都会改变高优先级

线程正在相互改变。 (当然开头和结尾的情况不同,但最高线程应该总是得到更多的时间片)

为什么不是一直这样? 低优先级线程必须执行更少的时间

【问题讨论】:

  • 如果 millisecondsTimeout 参数的值为零,则线程将其时间片的剩余部分交给任何准备好运行的具有相同优先级的线程...您的主线程尚未准备好运行它正在等待 t 和 t2 完成(Join 方法)
  • 这个测试因为看不到锁而搞砸了。它隐藏在 Console 类中,它确保一次只有一个线程可以执行 Console.Write()。它确保输出不会混合。这些线程不执行任何真正的代码,它们只是在争夺那个锁。操作系统线程调度程序会提高等待锁的线程的优先级并可以获取它。在 Sleep(0) 之后插入 for (long j = 0; j &lt; 1000L * 1000 * 50; j++) ;,从而让这些线程真正工作,您现在看到了您希望的结果。

标签: c# multithreading thread-priority


【解决方案1】:

您有 2 个线程:t(高优先级)和 t2(低优先级),还有主线程。当高优先级线程执行Thread.Sleep(0) 时——它可以给它的时间片的唯一其他线程是t2,因为即使它的优先级较低——也没有其他选择。主线程被Join()阻塞,没有代码可以运行,不需要时间片。

要查看您所期望的行为 - 再添加一个具有高优先级的线程:

public static void Main() {
    Thread.CurrentThread.Priority = ThreadPriority.Normal;
    Thread t = new Thread(new ThreadStart(ThreadMethod));
    t.Priority = ThreadPriority.Highest;

    Thread t2 = new Thread(new ThreadStart(ThreadMethod));
    t2.Priority = ThreadPriority.Lowest;

    Thread t3 = new Thread(new ThreadStart(ThreadMethod));
    t3.Priority = ThreadPriority.Highest;

    Process.GetCurrentProcess().ProcessorAffinity = (System.IntPtr) 1;

    t.Start();
    t2.Start();
    t3.Start();
    t3.Join();
    t2.Join();
    t.Join();
}

然后您会看到高优先级线程将它们的时间片分配给彼此,因此它们几乎都将完全执行它们的循环,并且只有在它们完成后 - 低优先级线程才会执行它的循环。

【讨论】:

  • 看起来你是绝对正确的,只是与 MSDN 上的描述和有关 Thread.Sleep(0) MSDN 的其他讨论混淆:“如果没有其他同等优先级的线程可以运行,则执行当前线程没有挂起。”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-29
  • 1970-01-01
  • 2014-11-26
  • 1970-01-01
  • 2011-04-19
  • 1970-01-01
相关资源
最近更新 更多