在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爲了它來執行(這已經是由低優先級任務獲得),高優先級任務被執行死刑只是爲了找出它不能執行!因此,編譯器不會進行任何優化,以防止在任務需要執行資源時進行不必要的上下文切換。