【发布时间】:2014-04-19 09:14:04
【问题描述】:
自旋锁可能仅在具有真正并行性的系统(即多核/处理器系统)上有效。由于他们的设计,这并不奇怪。
尽管如此,共享资源的线程必须在不同的内核上执行。否则情况类似于单处理器系统。
仅仅是概率问题还是调度程序试图将互锁线程放在不同的 CPU 上以提供真正的并发性?
【问题讨论】:
标签: .net multithreading spinlock
自旋锁可能仅在具有真正并行性的系统(即多核/处理器系统)上有效。由于他们的设计,这并不奇怪。
尽管如此,共享资源的线程必须在不同的内核上执行。否则情况类似于单处理器系统。
仅仅是概率问题还是调度程序试图将互锁线程放在不同的 CPU 上以提供真正的并发性?
【问题讨论】:
标签: .net multithreading spinlock
当涉及两个线程时,自旋锁可能是有效的,因为当一个线程正在等待时,另一个线程释放锁的可能性很大。因此,您是正确的,没有任何保证,并且涉及很多可能性。结果,您等待带有自旋锁的锁仅具有持有很短时间的锁。因为获取锁的线程显然在获取锁的时候正在执行,所以如果线程持有很短的时间,很有可能该线程还在执行释放锁。
然而,当涉及 IO 时,自旋锁也可能有效,即当一个线程没有在另一个线程上等待,而是在一个硬件事件发出数据即将到来的信号时,特别是如果该数据很快就会出现(例如等待正在执行的硬件功能)。
【讨论】:
线程上下文切换的成本是自旋锁有用的原因。对于 Windows 上的开关,引用的通常数字在 2000 到 10,000 个 cpu 周期之间。与必须存储和重新加载处理器状态以及由于保证的高速缓存未命中而导致的停顿相关的成本。这纯粹是开销,没有做任何有用的事情。
因此,如果一个程序等待一个锁可用,它会消耗数千个周期并定期尝试进入锁,它可以执行得更好。如果期望锁很快变得可用,这可以避免上下文切换。
没有计时器可用于等待如此短的持续时间,它是通过使用小循环实际燃烧循环来实现的。纺纱。这在处理器级别得到支持,专用的 PAUSE 机器代码指令可用于降低在 Intel/AMD 内核上旋转时的功耗。 .NET 中的 Thread.Yield() 和 Thread.SpinWait() 充分利用了它。
实际上在代码中有效地使用自旋锁可能会很棘手,当然只有在获得锁的几率足够高的情况下才能正常工作。如果它们不是,那么自旋锁是有害的,因为它会延迟上下文切换,这可能需要让另一个线程重新获得处理器并释放锁。 .NET 4.0 SpinLock 类很有用,它为失败的旋转生成ETW events。否则well documented.
【讨论】: