3

C# では、優先度の高いタスクを実行する準備ができており、別の (優先度の低い) スレッドが既にモニター内にある場合、優先度の低いタスクは次の 2 つのシナリオでプリエンプトされます。

  1. 優先度の高いタスクは、優先度の低いタスクによって取得された 1 つ (または複数) のロックを取得する必要があります。
  2. 優先度の高いタスクは、優先度の低いタスクによって取得されたロックを必要としません。

コンパイラ/OS は、タスクのプリエンプションに関して何か賢いことをしますか?それとも、優先度の高いタスクが優先度の低いタスクを常にプリエンプトするというのは常にそうですか?

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 に答える