在C#中,如果高优先级的任务准备好执行和其他(低优先级)的线程已经是显示器内部,将低优先级的任务在以下两种情况下被抢占:C#,线程优先级,并锁定
- 较高优先级任务想要获取由低优先级任务获取的一个(或多个)锁。
- 优先级较高的任务不需要由低优先级任务获取的任何锁。
编译器/操作系统是否在任务抢占方面做了任何聪明的事情,还是总是出现优先级较高的任务始终抢占较低优先级的任务?
在C#中,如果高优先级的任务准备好执行和其他(低优先级)的线程已经是显示器内部,将低优先级的任务在以下两种情况下被抢占: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!
}
}
以下是该程序的输出:
低优先级任务执行
低优先级的任务将不会释放锁!
高优先级任务执行
虽然高优先级任务需要获取resourcelock为了它来执行(这已经是由低优先级任务获得),高优先级任务被执行死刑只是为了找出它不能执行!因此,编译器不会进行任何优化,以防止在任务需要执行资源时进行不必要的上下文切换。