我如何能重现一个线程阻塞无限期(以下邮政编码)
本文关键字:无限期 邮政编码 线程 一个 何能重 | 更新日期: 2023-09-27 18:03:10
我正在努力理解这个问题(以及它的答案):
- ThreadA和ThreadB都以相同的AutoResetEvent的顺序调用WaitOne() -当事件被设置时,为什么ThreadB被释放而不是ThreadA?
代码
代码中的注释告诉我们:
// set the event - I thought this would mean both waiting threads are allowed to continue
// BUT thread2 runs and thread1 stays blocked indefinitely
但是我不明白为什么任何线程可以被无限期地阻塞…
我试图运行代码,我不能观察到任何无限期阻塞…
在这个问题(和相应的答案)中我错过了什么?
private static void Test()
{
// two threads - waiting for the same autoreset event
// start it unset i.e. closed i.e. anything calling WaitOne() will block
AutoResetEvent autoEvent = new AutoResetEvent(false);
Thread thread1 = new Thread(new ThreadStart(WriteSomeMessageToTheConsole));
thread1.Start(); // this will now block until we set the event
Thread thread2 = new Thread(new ThreadStart(WriteSomeOtherMessageToTheConsole));
thread2.Start(); // this will now also block until we set the event
// simulate some other stuff
Console.WriteLine("Doing stuff...");
Thread.Sleep(5000);
Console.WriteLine("Stuff done.");
// set the event - I thought this would mean both waiting threads are allowed to continue
// BUT thread2 runs and thread1 stays blocked indefinitely
// So I guess I was wrong and that Set only releases one thread in WaitOne()?
// And why thread2 first?
autoEvent1.Set();
}
更新:我启动这段代码为:
using System;
using System.Threading;
namespace bothCallWaitOne
{
class Program
{
static void Main(string[] args)
{
// two threads - waiting for the same autoreset event
// start it unset i.e. closed i.e. anything calling WaitOne() will block
AutoResetEvent autoEvent = new AutoResetEvent(false);
WriteSomeMessageToTheConsole();
Thread thread1 = new Thread(new ThreadStart(WriteSomeMessageToTheConsole));
thread1.Name = "1111111111";
thread1.Start(); // this will now block until we set the event
//Thread thread2 = new Thread(new ThreadStart(WriteSomeOtherMessageToTheConsole));
Thread thread2 = new Thread(new ThreadStart(WriteSomeOtherMessageToTheConsole));
thread2.Name = "222222222222";
thread2.Start(); // this will now also block until we set the event
// simulate some other stuff
Console.WriteLine("Doing stuff...");
Thread.Sleep(5000);
Console.WriteLine("Stuff done.");
// set the event - I thought this would mean both waiting threads are allowed to continue
// BUT thread2 runs and thread1 stays blocked indefinitely
// So I guess I was wrong and that Set only releases one thread in WaitOne()?
// And why thread2 first?
autoEvent.Set();
Console.ReadLine();
}
static void WriteSomeMessageToTheConsole()
{
Console.WriteLine(Thread.CurrentThread.Name);
}
static void WriteSomeOtherMessageToTheConsole()
{
Console.WriteLine(Thread.CurrentThread.Name);
}
}
}
我没有观察到任何不确定的阻塞。
下面是运行代码后的输出:Doing stuff...
222222222222
1111111111
Stuff done.
我应该如何运行(更新,更改,增量)的代码,以重现讨论的主题(有一个线程被无限期地阻塞)?
From MSDN
- AutoResetEvent保持信号状态,直到单个等待线程被释放。
AutoResetEvent的工作原理是旋转门。一次Set
调用只释放一个线程。
ARE是一只奇怪的野兽。如果您读取它的MSDN条目,您将发现,如果在多个线程正在等待时发出一次信号,它将只释放一个等待线程。然而,如果当它发出信号时没有线程在等待,它就不会保持信号的计数,并且它被'丢失'。
这是一个介于手动重置事件和信号量之间的奇怪混合体。老实说,我觉得它没有任何一个有用:)
下面是重现这个问题的最终代码。
注意,autoEvent
不能是本地的,以便在其他方法中看到,它应该是静态的,以便从静态Main()
和Test()
方法中使用,然后从静态方法中"使用"它:
using System;
using System.Threading;
namespace bothCallWaitOne
{
class Program
{
static AutoResetEvent autoEvent = new AutoResetEvent(false);
static void Main(string[] args)
{
Test();
Console.ReadLine();
}
private static void Test()
{
// two threads - waiting for the same autoreset event
// start it unset i.e. closed i.e. anything calling WaitOne() will block
//AutoResetEvent autoEvent = new AutoResetEvent(false);
//WriteSomeMessageToTheConsole();
Thread thread1 = new Thread(new ThreadStart(WriteSomeMessageToTheConsole));
thread1.Name = "1111111111";
thread1.Start(); // this will now block until we set the event
//Thread thread2 = new Thread(new ThreadStart(WriteSomeOtherMessageToTheConsole));
Thread thread2 = new Thread(new ThreadStart(WriteSomeOtherMessageToTheConsole));
thread2.Name = "222222222222";
thread2.Start(); // this will now also block until we set the event
// simulate some other stuff
Console.WriteLine("Doing stuff...");
Thread.Sleep(5000);
Console.WriteLine("Stuff done.");
// set the event - I thought this would mean both waiting threads are allowed to continue
// BUT thread2 runs and thread1 stays blocked indefinitely
// So I guess I was wrong and that Set only releases one thread in WaitOne()?
// And why thread2 first?
autoEvent.Set();
}
static void WriteSomeMessageToTheConsole()
{
autoEvent.WaitOne();//Cannot relve symbol autoEvent
while(true)
Console.WriteLine(Thread.CurrentThread.Name+"****");
}
static void WriteSomeOtherMessageToTheConsole()
{
autoEvent.WaitOne();//Cannot relve symbol autoEvent
while(true)
Console.WriteLine(Thread.CurrentThread.Name);
}
}
}