我如何能重现一个线程阻塞无限期(以下邮政编码)

本文关键字:无限期 邮政编码 线程 一个 何能重 | 更新日期: 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);
    }
  }
}