AutoResetEvent和maximumCount=1的信号量之间有什么区别吗

本文关键字:之间 什么 区别 信号量 maximumCount AutoResetEvent | 更新日期: 2023-09-27 18:00:18

我正在阅读以下文章:

http://www.albahari.com/threading

并且我无法意识到AutoResetEvent和用maximumCount=1初始化的信号量之间的区别。只是想看看我是否做对了。。。考虑到这种用法,这两个结构有什么区别吗?

谢谢!

AutoResetEvent和maximumCount=1的信号量之间有什么区别吗

是的,肯定有区别。Semaphore用于限制对资源或代码块的访问。当调用WaitOne时,线程将阻塞,直到信号量中的计数可用为止。若要进行计数,请致电Release。最大计数为1的信号量通常称为二进制信号量。这种性质的信号量只允许从单个线程访问资源或块代码。您可以使用二进制信号量来代替互斥或监视器。关于Semaphore,需要记住的重要一点是,它的状态是通过调用WaitOneRelease手动控制的。

另一方面,CCD_ 7主要用作信令机制。一个线程将通过对WaitOne的调用进行阻塞,等待信号。另一个线程将调用Set来启动该信号。ARE将此信号发布到一个且只有一个线程,然后立即将ARE重置为无信号状态。关于AutoResetEvent,需要记住的重要一点是,它是通过对Set的调用来手动发出信号的,并且当对WaitOne的单个调用返回时,会自动重置。

以下是差异总结:

  • Semaphore的状态是手动控制的
  • AutoResetEvent的状态是手动设置的,但会自动重置
  • 对于Semaphore,线程通常平衡ReleaseWaitOne调用
  • 对于AutoResetEvent,一个线程通常被指定为信号员,另一个线程被指定为服务员
  • Semaphore限制对资源或代码块的访问
  • AutoResetEvent用信号通知线程采取一些操作

AutoResetEvent想象成通往走廊的门。在收到命令后,门将允许一个人通过。一旦一个人通过门,门就会立即关闭,等待另一个命令。只要门不断收到新的命令,走廊就可以自由地容纳与发出的命令数量一样多的人。

Semaphore想象成通往同一走廊的门。这扇门将允许一定数量的人进入走廊。门一直打开,直到走廊达到其占用限制,此时门关闭。有人从另一边离开走廊后,这扇门又打开了。

更新:

以下是一个最简单的例子,它表明某些东西显然是不同的。

static void Main()
{
    var are = new AutoResetEvent(false);
    are.Set();
    are.Set();
    var semaphore = new Semaphore(0, 1);
    semaphore.Release();
    semaphore.Release();
}

毫不奇怪,您会在第二次semaphore.Release调用中得到异常,而对Set的第二次调用通过得很好。原因是ARE正在设置布尔标志,而信号量正试图增加计数。

WaitOne方法将以相同的方式工作,但ReleaseSet方法不会。正是由于这个原因,二进制信号量不能与ARE互换。然而,在某些情况下,ARE可以与二进制信号交换。

存在重叠的一种情况是在单个线程的锁存器的情况下。

public static void Main()
{
  var latch = new AutoResetEvent(false);
  new Thread(
    () =>
    {
      latch.WaitOne(); // Wait for the latch.
    }).Start();
  latch.Set(); // Release the latch.
}

这是一个只有AutoResetEvent才能满足的场景。

static void Main()
{
    var are = new AutoResetEvent(false);
    new Thread(
        () =>
        {
            while (true)
            {
                are.WaitOne();
                Console.WriteLine("go");
                Thread.Sleep(2000);
            }
        }).Start();
    while (true)
    {
        are.Set();
        Console.WriteLine("pulse");
        Thread.Sleep(1000);
    }
}

一个AutoResetEvent,用Joe Albahari的比喻:

就像一个检票口:插入一张票可以让一个人通过

所以它就像一扇单向门。

相比之下,计数为1的Semaphore就像一个只能容纳一个人的房间,它有一个"已占用"的标志。信号灯用于控制对资源(房间)的访问,计数指定有多少资源(房间可以容纳多少人)。

从用户的角度来看,大多数情况下都是一样的,一个小的区别是AutoResetEvent上的多个连续信号将成功,这使得对资源生产消耗问题进行建模变得不合适。看看这篇文章-";自动重置事件只是一个愚蠢的信号量;。

最大值为1的信号量就像一个正常的System.Threading.Monitor或锁"如果我们忽略命名系统信号量在整个操作系统中可见的事实…"这提供了一个关键部分等待线程,该线程被阻塞,直到当前线程完成对资源"."的使用,因此只有一个线程可以访问一个资源。

您可以将AutoResetEvent视为通知程序,一个线程将等待,直到收到来自另一个线程的通知才能继续,而另一个稍后将设置为使另一线程再次等待通知"注意,AutoResetEventwill automatically set the waiting thread again"。。。

AutoRestEvent的一个例子是生产者/消费者使用集合,第一个线程将等待并添加元素来消费它,另一个线程"生产者"每当添加元素时都会发出信号"通知"等待通知的线程"被阻止等待通知",然后第一个线程将处理"消费"新添加的元素,然后再次等待,直到添加另一个元素。。

//编辑:如果您已经知道AutoResetEventSemaphore之间的区别,并询问"作为您的评论"

如果我们限制自己只使用WaitOne和Set进行ARE

如果您只使用_autoResetEvent.WaitOne()_autoResetEvent.Set(),那么您可以获得相同的结果-但您应该小心使用-通过使用_semaphore.WaitOne()_semaphore.Release():

AutoResetEVent _autoResetEvent = new AutoResetEvent(true);
Semaphore _semaphore = new Semaphore(1, 1);
private void Foo()
{
    _autoResetEvent.WaitOne();
    try
    {
        //some code
        Console.WriteLine("Thread At Foo Entered {0}", Thread.CurrentThread.ManagedThreadId);
    }
    finaly
    {
        _autoResetEvent.Set();
    }
}
private void Bar()
{
    _semaphore.WaitOne();
    try
    {
        //some code
        Console.WriteLine("Thread At Bar Entered {0}", Thread.CurrentThread.ManagedThreadId);
    }
    finaly
    {
        _semaphore.Release();
    }
}
void Main()
{
    new Thread(Foo) { IsBackground = true }.Start();
    new Thread(Foo) { IsBackground = true }.Start();
    new Thread(Bar) { IsBackground = true }.Start();
    new Thread(Bar) { IsBackground = true }.Start();
    Thread.Sleep(2000);//give it some time to execute.
    Console.ReadLine();
}
//output is something like this:
Thread At Foo Entered 11
Thread At Foo Entered 12
Thread At Far Entered 13
Thread At Far Entered 14

信号量用于控制对关键部分的访问。当您想向其他线程发出某个事件已经发生的信号,以便他们对此做出反应时,会使用Auto/ManualResetEvent——它们实际上与保护进入关键部分无关。

我不确定你指的是哪种特定的用法,但我想你可以使用锁和事件来实现信号量,所以你的问题的答案可能是否定和肯定,这取决于你想要什么。

相关文章: