1

在使用 C Sharp's Barrier 时,我遇到了一个非常奇怪的死锁。目的是看看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的时候停下来(障碍数只有 1)?barrier.SignalAndWait();

感谢您的观看和任何帮助。

解决方案总结:

这个问题是平台相关的。由于在非本机平台上运行它,我遇到了死锁。我尝试使用 2 个在线编译器(1)http://www.compileonline.com/compile_csharp_online.php,(2)https://compilr.com/并陷入僵局。第一个唯一的编译器使用 mono 来执行 windows 可执行文件(它是非本地的)。我不确定第二个在线编译器的平台。

但是,正如 and 所建议的Phillip Scott Givenssvick我在运行 .Net 4.0 的 Visual C# 2010 上本地安装并运行了该示例,并且死锁消失了。

4

0 回答 0