在使用 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 Givens
,svick
我在运行 .Net 4.0 的 Visual C# 2010 上本地安装并运行了该示例,并且死锁消失了。