在什么情况下应该使用以下每个同步对象?
- 读写锁
- 信号
- Mutex
由于每次调用 post() 时 wait() 都会返回一次,因此信号量是一种基本的生产者-消费者模型 - 除了信号之外最简单的线程间消息形式。使用它们是为了让一个线程可以告诉另一个线程发生了它感兴趣的事情(以及发生了多少次),并用于管理对最多可以有固定有限数量的用户的资源的访问。它们提供多线程代码所需的排序保证。
互斥体执行其表面上所说的操作 - “互斥”。它们确保一次仅由一个线程“持有”访问某些资源的权利。这保证了多线程代码所需的原子性和顺序。在大多数操作系统上,它们还提供相当复杂的等待行为,特别是为了避免优先级倒置。
请注意,信号量可以轻松地用于实现互斥,但由于信号量没有“所有者线程”,因此您无法使用信号量来避免优先级反转。因此它们并不适合所有需要“锁”的用途。
ReaderWriter 锁是对互斥体的优化,在存在大量争用的情况下,大多数访问都是只读的,并且受保护的数据结构允许同时读取。在这种情况下,仅当涉及作者时才需要排除 - 读者不需要相互排除。为了将读取器提升为写入器,所有其他读取器必须在获取写入器锁之前完成(或者如果他们也希望成为写入器,则中止并开始等待重试)。 ReaderWriter 锁在速度不快的情况下可能会更慢,因为它们在互斥锁上进行了额外的簿记操作。
条件变量用于允许线程等待某些事实或事实组合为真,其中所讨论的条件比信号量中的“它已被戳”或互斥体中的“没有其他人使用它”更复杂读写器锁的写入者部分,或者对于读写器锁的读取器部分“没有写入者正在使用它”。它们还用于不同等待线程的触发条件不同但取决于部分或全部相同状态(内存位置或其他)的情况。
自旋锁适用于当您在一个处理器或内核上等待很短的时间(例如几个周期),而另一个内核(或硬件,例如 I/O 总线)同时执行一些您关心的工作时关于。在某些情况下,它们比其他原语(例如信号量或中断)提供了性能增强,但必须极其小心地使用(因为无锁算法在现代内存模型中很困难)并且仅在被证明有必要时才使用(因为避免系统原语的聪明想法)通常是过早的优化)。
顺便说一句,这些答案不是特定于 C# 的(因此例如关于“大多数操作系统”的评论)。 Richard 提出了一个很好的观点,即在 C# 中,您应该在适当的情况下使用普通的旧锁。我相信监视器是一对滚入一个对象的互斥体/条件变量。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)