当使用C Sharp的屏障时,我想出了一个非常奇怪的僵局。目的是了解RemoveParticipants()
实际上是如何运作的。我从2个线程(2个动作)开始,每个执行barrier.SignalAndWait();
。之后,一个线程将删除一个参与者。从那时起,屏障计数仅为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]
另一个注意事项是,如果我在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
在barrier.SignalAndWait();
停止时会停止(屏障数只有1)?
感谢您查看和提供任何帮助。
解决方案摘要:
此问题与平台有关。由于在非本地平台上运行它,我遇到了死锁。我尝试使用2个在线编译器(1)http://www.compileonline.com/compile_csharp_online.php,(2)https://compilr.com/并解决了僵局。第一个唯一的编译器使用mono执行Windows可执行文件(非本机)。我不确定第二个在线编译器的平台。
但是,正如
Phillip Scott Givens
和svick
所建议的那样,我在运行.Net 4.0的Visual C#2010上本机安装并运行了示例,并且死锁消失了。