由于C#'中的RemoveParticipants导致了奇怪的僵局;s屏障类
我在使用C夏普的屏障时遇到了一个非常奇怪的死锁。目的是了解由于C#'中的RemoveParticipants导致了奇怪的僵局;s屏障类,c#,barrier,C#,Barrier,我在使用C夏普的屏障时遇到了一个非常奇怪的死锁。目的是了解RemoveParticipants()实际上是如何工作的。我从2个线程(2个操作)开始,每个线程执行barrier.SignalAndWait()。之后,一个线程将删除一个参与者。由于这一点,屏障计数仅为1。右边是所有剩余的barrier.SignalAndWait()应在没有任何死锁的情况下通过。但是,以下程序处于死锁状态 using System; using System.Threading; using System.Threa
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
我不知道为什么上面的程序会死锁?为什么操作2
在障碍物处停止。SignalAndWait()代码>当它应该通过时(屏障计数仅为1)
感谢您的观看和任何帮助
解决方案摘要:
这个问题取决于平台。由于在非本机平台上运行,我遇到了死锁。我使用2个在线编译器(1)、(2)进行了尝试,结果出现了死锁。第一个编译器使用mono执行windows可执行文件(非本机)。我不确定第二个在线编译器的平台
然而,正如Phillip Scott Givens和svick的建议,我在运行.Net 4.0的Visual C#2010上安装并运行了本机示例,死锁消失了
我已经将您的代码复制到单元测试中,对我来说效果很好。这是我每次运行时的输出(很抱歉,我无法格式化此注释):操作1:phase=0;计数=2动作2:相位=0;计数=2动作1:相位=1;计数=2动作2:唤醒1动作1:相位=2;计数=1动作1:终止动作2:唤醒2动作2:阶段=2;计数=1动作2:阶段=3;count=1将要处理我甚至改变了对任务1和任务2的评论,正如你所说的,它可以工作。很奇怪。我没有使用过屏障,但现在你已经确认你的代码在某人的计算机上工作。我没有遇到死锁。但这可能是因为我在.NET4.5上。谢谢你的信息,菲利普·斯科特·吉文斯和斯维克。我在VisualStudio2010上用.NET4.0对其进行了测试,无法重现死锁。我可能会得出结论,问题出现在非本机平台上。@PhillipScottGivens正如您所知,您可以通过在代码周围加上`标记来格式化注释中的代码。