1

C Sharp's Barrier を使用すると、非常に奇妙なデッドロックが発生しました。RemoveParticipants()意図は、実際にどのように機能するかを確認することです。私は 2 つのスレッド (2 つのアクション) から始めましたbarrier.SignalAndWait();。その後、1 つのスレッドが 1 人の参加者を削除します。この時点から、バリア カウントは 1 のみですbarrier.SignalAndWait();。ただし、以下のプログラムはデッドロックです。

using System;
using System.Threading;
using System.Threading.Tasks;

class BarrierDemo
{
    /* Print out barrier's phase and count */
    static void printInfo(int action, Barrier b){
        Console.WriteLine("action {0} : phase = {1} ; count = {2} ",action, b.CurrentPhaseNumber, b.ParticipantCount);
    }

    static void Main(string[] args)
    {
        Barrier barrier = new Barrier(2);

        Action action1 = () =>
        {
            printInfo(1,barrier);

            barrier.SignalAndWait();

            //Thread.Sleep(1000);

            printInfo(1,barrier);

            barrier.SignalAndWait();

            printInfo(1,barrier);

            Console.WriteLine("action 1: terminating");
        };

        Action action2 = () =>
        {
            printInfo(2,barrier);

            barrier.SignalAndWait();

            Thread.Sleep(1000);
            Console.WriteLine("action 2 : wake up 1 ");
            barrier.RemoveParticipants(1);
            Thread.Sleep(1000);
            Console.WriteLine("action 2 : wake up 2 ");
            printInfo(2,barrier);

            barrier.SignalAndWait(); // **DEADLOCK HERE**

            printInfo(2,barrier);
        };

        /* Execute 2 actions in parallel */
        Parallel.Invoke(action1,action2);

        Console.WriteLine("Going to dispose");
        barrier.Dispose();

    }

}

トレース中に受け取った出力は次のとおりです。

action 1 : phase = 0 ; count = 2
action 2 : phase = 0 ; count = 2
action 1 : phase = 1 ; count = 2
action 2 : wake up 1
action 1 : phase = 2 ; count = 1
action 1: terminating
action 2 : wake up 2
action 2 : phase = 2 ; count = 1
[Deadlock]

もう 1 つの注意点は、action2 のすべての System.Sleep() をコメント化し、action1 の System.Sleep() を非コメント化する場合です。その後、プログラムは終了します。

action 1 : phase = 0 ; count = 2
action 2 : phase = 0 ; count = 2
action 2 : wake up 1
action 2 : wake up 2
action 2 : phase = 1 ; count = 1
action 2 : phase = 2 ; count = 1
action 1 : phase = 2 ; count = 1
action 1 : phase = 3 ; count = 1
action 1: terminating
Going to dispose

上記のプログラムがデッドロックする理由がわかりません。通過するはずの時間でaction2停止するのはなぜですか(バリアカウントは 1 のみです)。barrier.SignalAndWait();

ご覧いただきありがとうございます。

ソリューションの概要:

この問題はプラットフォームに依存します。ネイティブ以外のプラットフォームで実行したためにデッドロックが発生しました。2 つのオンライン コンパイラ (1) http://www.compileonline.com/compile_csharp_online.php、(2) https://compilr.com/を使用して試してみたところ、デッドロックが発生しました。最初の唯一のコンパイラは、mono を使用して Windows 実行可能ファイル (非ネイティブ) を実行します。2 番目のオンライン コンパイラのプラットフォームについてはわかりません。

Phillip Scott Givensただし、およびで示唆されているようsvickに、.Net 4.0 を実行している Visual C# 2010 にサンプルをネイティブにインストールして実行したところ、デッドロックは解消されました。

4

0 に答える 0