【问题标题】:Does locking on a Semaphore object make any sense?锁定 Semaphore 对象是否有意义?
【发布时间】:2019-07-30 06:19:17
【问题描述】:

我遇到了一个使用信号量作为锁定对象的代码。我问了我的同事,他们说,如果我们想监控锁的状态,或者代码深处发生奇怪的异常并且 CLR 无法回滚堆栈,或者其他什么,这可能很有意义这样,锁没有正常释放,我们可以手动释放。

我从来没有听说过这些现象,也没有发现任何关于这些的东西,所以我对整个事情持怀疑态度。我认为这只是一种不好的做法,因为您会混淆如何使用 Semaphore 对象。有人可以确认吗?

private Semaphore _semaphore = new Semaphore(0, 1);

public void DoSomethingThreadSafe()
{
    lock (_semaphore)
    {
        //some code
    }
}

【问题讨论】:

  • lock 被转换为对Monitor 的调用。即使太阳风暴导致程序无法释放锁,您也无法使用 Semaphore 释放它。项目中是否有任何代码以另一种方式访问​​信号量?
  • 一个锁只允许一个线程进入被锁定的部分,并且该锁不与任何其他进程共享。互斥锁与锁相同,但它可以是系统范围的(由多个进程共享)。 ..
  • 锁定信号量本身与锁定任何其他类型的对象没有什么不同。当然,直接在锁内按预期使用信号量(WaitOne/Release)是没有意义的,因为它违背了信号量的目的。我想这取决于锁内部发生了什么,以及信号量是否在系统中以任何其他方式被访问和使用。
  • 是的,我也有同样的感受,谢谢你的支持。在函数中的信号量上只调用了一次 Release(),但没有使用它。也许它无论如何都行不通。我重构了代码,并将这些信号量变成了对象。我只是好奇,它在其他应用程序中是否可能有什么意义,但似乎没有。

标签: c# locking semaphore


【解决方案1】:

与任何其他对象类型相比,锁定信号量对象不会带来任何额外的好处,但可能会损害可读性,因为它不是执行此类操作的惯用方式:

如果我们想监控锁的状态

lock 机制与用于同步的对象类型绝对无关,并且不会尝试将Semaphore 实例与另一个实例区分开来以执行某些Semaphore 特定的操作。实际发生的情况是,Monitor.EnterMonitor.Exit 方法用于 lock 构造的生成代码中,这些方法在内部使用 CLR 对象头(它是任何引用类型内存布局的一部分)和/或同步块,它是实例标头引用的特殊表中的条目。因此,除了获取 CLR 维护的内部同步状态的 hacky 方法之外,没有其他方法可以监控用于同步的对象的状态。

或者如果代码深处发生了奇怪的异常,CLR无法回滚堆栈,或者类似的情况,并且锁没有正确释放,我们可以手动释放它

同样,信号量作为Semaphore 实例的状态与同步对象的状态无关,同步对象恰好是信号量实例内存布局的一部分,并由lock 机制在内部使用,并且进入或离开lock 块不会导致更改信号量计数以及释放信号量对用于lock 的同步对象没有任何影响。因此,在这种情况下使用信号量不会带来任何好处,而且如果在 CRL 无法展开堆栈时出现问题,那么应用程序代码能否在这种情况下执行某些操作是非常值得怀疑的。

【讨论】:

    猜你喜欢
    • 2014-04-10
    • 1970-01-01
    • 1970-01-01
    • 2010-11-20
    • 2021-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-12
    相关资源
    最近更新 更多