应该何时使用每个线程同步对象?

在什么情况下应该使用以下每个同步对象?

  1. ReaderWriter锁定
  2. 信号
  3. 互斥

  • 因为每次调用post()时wait()都会返回一次,所以信号量是一个基本的生产者 – 消费者模型 – 除了信号之外最简单的线程间消息forms。 它们被使用,因此一个线程可以告诉另一个线程发生了它感兴趣的事情(以及多少次),以及管理对最多只能拥有固定有限数量用户的资源的访问。 它们提供multithreading代码所需的订购保证。

  • 互斥体做了他们对锡的说法 – “相互排斥”。 它们确保访问某些资源的权限一次只能在线程上“保留”。 这样可以保证multithreading代码所需的primefaces性和排序。 在大多数操作系统上,它们还提供相当复杂的服务员行为,特别是为了避免优先级倒置。

请注意,信号量可以很容易地用于实现互斥,但由于信号量没有“所有者线程”,因此您不会使用信号量获得优先级反转。 因此它们不适合所有需要“锁定”的用途。

  • ReaderWriter锁是对互斥锁的优化,如果您有很多争用,大多数访问都是只读的,并且允许同时读取受保护的数据结构。 在这种情况下,只有在涉及作者时才需要排除 – 读者不需要彼此排除。 为了促进读者写作,所有其他读者必须在获得作者锁定之前完成(或中止并开始等待重试,如果他们也希望成为作者)。 在没有更快的情况下,ReaderWriter锁可能会更慢,因为它们会通过互斥锁进行额外的簿记。

  • 条件变量用于允许线程等待某些事实或事实组合为真,其中所讨论的条件比信号量的“已被戳”更复杂,或者“没有其他人使用它”用于互斥量和读写器锁的编写器部分,或者“没有编写者正在使用它”,用于读写器锁的读取器部分。 它们也用于不同等待线程的触发条件不同的情况,但取决于部分或全部相同的状态(存储器位置或其他)。

  • 旋转锁用于在一个处理器或内核上等待很短的时间(如几个周期),而另一个内核(或I / O总线等硬件)同时执行您关心的一些工作关于。 在某些情况下,它们比其他原语(如信号量或中断)提供性能增强,但必须非常谨慎地使用(因为现代内存模型中的无锁算法很困难),并且只有在certificate有必要时才会使用(因为明智的想法可以避免系统原语)往往是过早优化)。

顺便说一句,这些答案不是C#特定的(因此例如关于“大多数操作系统”的评论)。 理查德提出了一个很好的观点,即在C#中你应该使用普通的旧锁。 我相信监视器是一个互斥/条件变量对,卷入一个对象。

我会说他们每个人都可以“最好” – 取决于用例;-)

简单回答:几乎从不。

最好的锁定类型是不需要锁(没有共享的可变状态)。

如果您确实需要锁定,请尝试使用监视器(通过锁定语句),除非您对不同的东西有特定需求(在这种情况下请参阅Onebyone的答案)

此外,更喜欢ReaderWriteLockSlimReaderWriterLock (除非极少数情况下需要后者的公平性)。