在C#中,如果高优先级任务已准备好执行而另一个(低优先级)线程已在监视器内,则低优先级任务是否会在以下两种情况下被抢占:
优先级较高的任务想要获取由低优先级任务获取的一个(或多个)锁 .
优先级较高的任务不需要低优先级任务获取的任何锁 .
编译器/操作系统是否在任务抢占方面做了任何聪明的事情,或者优先级较高的任务总是抢占优先级较低的任务?
如果优先级较高的线程正在等待锁定,则无论哪个线程拥有锁定,它都不会被调度 .
如果较高优先级的线程没有等待任何东西,那么它可以抢占较低优先级的线程 . 这些都不是真正的.NET或C#特定的 - 它最终归结为操作系统来管理线程并安排它们 .
你可能会发现this MSDN article on thread priorities很有用 - 它确实让我感到惊讶 . 特别是:
系统以循环方式将时间片分配给具有最高优先级的所有线程 . 如果这些线程都没有准备好运行,系统会以循环方式将时间片分配给具有下一个最高优先级的所有线程 . 如果更高优先级的线程可用于运行,则系统将停止执行优先级较低的线程(不允许它使用其时间片完成),并将全时时间片分配给优先级较高的线程 .
您应该能够通过创建一个程序来验证一些高优先级线程和一些低优先级线程;上面的引用表明,如果你可以让处理器忙于高优先级线程,那么低优先级线程将完全饿死 . 这让我感到惊讶,但你应该能够尝试并看看会发生什么 . 只是尝试保持高优先级线程忙于不会导致任何IO(等)的工作,否则会阻止它们 .
对于那些对问题的第一个场景感兴趣的人,以下是我在处理锁定时测试线程抢占所做的实验:
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! } }
以下是该计划的输出:
执行低优先级任务低优先级任务永远不会释放锁定!执行高优先级任务
虽然高优先级任务需要获取资源锁(已经由低优先级任务获取)才能执行,但执行高优先级任务只是为了发现它无法执行!!因此,当任务需要资源执行时,编译器无论如何都不进行优化以防止不必要的上下文切换 .
2 回答
如果优先级较高的线程正在等待锁定,则无论哪个线程拥有锁定,它都不会被调度 .
如果较高优先级的线程没有等待任何东西,那么它可以抢占较低优先级的线程 . 这些都不是真正的.NET或C#特定的 - 它最终归结为操作系统来管理线程并安排它们 .
你可能会发现this MSDN article on thread priorities很有用 - 它确实让我感到惊讶 . 特别是:
您应该能够通过创建一个程序来验证一些高优先级线程和一些低优先级线程;上面的引用表明,如果你可以让处理器忙于高优先级线程,那么低优先级线程将完全饿死 . 这让我感到惊讶,但你应该能够尝试并看看会发生什么 . 只是尝试保持高优先级线程忙于不会导致任何IO(等)的工作,否则会阻止它们 .
对于那些对问题的第一个场景感兴趣的人,以下是我在处理锁定时测试线程抢占所做的实验:
以下是该计划的输出:
虽然高优先级任务需要获取资源锁(已经由低优先级任务获取)才能执行,但执行高优先级任务只是为了发现它无法执行!!因此,当任务需要资源执行时,编译器无论如何都不进行优化以防止不必要的上下文切换 .