3

在 C# 中,如果一个高优先级任务已准备好执行并且另一个(低优先级)线程已经在监视器中,那么低优先级任务是否会在以下两种情况下被抢占:

  1. 较高优先级的任务想要获得一个(或多个)由低优先级任务获得的锁。
  2. 高优先级任务不需要低优先级任务获取的任何锁。

编译器/操作系统是否在任务抢占方面做了任何聪明的事情,还是总是高优先级任务总是抢占低优先级任务?

4

2 回答 2

5

对于那些对问题的第一个场景感兴趣的人,以下是我在处理锁定时测试线程抢占的一个实验:

object resourselock = new object();

    public void Test()
    {
        Thread lowestThread = new Thread(new ThreadStart(Low));
        lowestThread.Priority = ThreadPriority.Lowest;

        Thread highestThread = new Thread(new ThreadStart(High));
        highestThread.Priority = ThreadPriority.Highest;

        lowestThread.Start();
        Thread.Sleep(1000);   //makes sure that the lowest priority thread starts first
        highestThread.Start();
    }

    
    public void Low()
    {
        Console.WriteLine("Low priority task executed");

        lock (resourselock)
        {
            Console.WriteLine("Low priority task will never release the lock!");

            while (true) ; //infinite empty statement!
        }
    }

    public void High()
    {
        System.Console.WriteLine("High priority task executed");

        lock (resourselock)
        {
            System.Console.WriteLine("High priority task got the lock!"); //this will never be reached!
        }
    }

以下是程序的输出:

执行的低优先级任务

低优先级任务永远不会释放锁!

执行的高优先级任务

虽然高优先级任务需要获取资源锁(低优先级任务已经获取)才能执行,但执行高优先级任务却发现无法执行!!因此,当任务需要资源来执行时,编译器没有进行任何优化来防止不必要的上下文切换。

于 2013-09-27T18:27:50.633 回答
4

如果更高优先级的线程正在等待锁,则无论哪个线程拥有锁,都不会被调度。

如果较高优先级的线程没有等待任何东西,那么它可能会抢占较低优先级的线程。不过,这些都不是.NET 或 C# 特定的——它实际上最终取决于操作系统来管理线程并安排它们。

您可能会发现这篇关于线程优先级的 MSDN 文章很有用——它确实有几点让我感到惊讶。尤其是:

系统以循环方式将时间片分配给具有最高优先级的所有线程。如果这些线程都没有准备好运行,则系统以循环方式将时间片分配给具有下一个最高优先级的所有线程。如果较高优先级的线程可以运行,系统将停止执行较低优先级的线程(不允许它完成使用其时间片),并将完整的时间片分配给较高优先级的线程。

应该能够通过创建一个包含一些高优先级线程和一些低优先级线程的程序来验证这一点;上面的引用表明,如果您可以让处理器忙于高优先级线程,那么低优先级线程将完全饿死。这让我感到惊讶,但你应该能够进行实验,看看会发生什么。只需尝试让高优先级线程忙于不会导致任何 IO(等)的工作,否则会导致它们停止。

于 2013-09-25T05:53:11.850 回答