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 にサンプルをネイティブにインストールして実行したところ、デッドロックは解消されました。