由于C#'中的RemoveParticipants导致了奇怪的僵局;s屏障类

由于C#'中的RemoveParticipants导致了奇怪的僵局;s屏障类,c#,barrier,C#,Barrier,我在使用C夏普的屏障时遇到了一个非常奇怪的死锁。目的是了解RemoveParticipants()实际上是如何工作的。我从2个线程(2个操作)开始,每个线程执行barrier.SignalAndWait()。之后,一个线程将删除一个参与者。由于这一点,屏障计数仅为1。右边是所有剩余的barrier.SignalAndWait()应在没有任何死锁的情况下通过。但是,以下程序处于死锁状态 using System; using System.Threading; using System.Threa

我在使用C夏普的屏障时遇到了一个非常奇怪的死锁。目的是了解
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正如您所知,您可以通过在代码周围加上`标记来格式化注释中的代码。