【问题标题】:What provides spinlocks effectiveness?什么提供了自旋锁的有效性?
【发布时间】:2014-04-19 09:14:04
【问题描述】:

自旋锁可能仅在具有真正并行性的系统(即多核/处理器系统)上有效。由于他们的设计,这并不奇怪。

尽管如此,共享资源的线程必须在不同的内核上执行。否则情况类似于单处理器系统。

仅仅是概率问题还是调度程序试图将互锁线程放在不同的 CPU 上以提供真正的并发性?

【问题讨论】:

    标签: .net multithreading spinlock


    【解决方案1】:

    当涉及两个线程时,自旋锁可能是有效的,因为当一个线程正在等待时,另一个线程释放锁的可能性很大。因此,您是正确的,没有任何保证,并且涉及很多可能性。结果,您等待带有自旋锁的锁仅具有持有很短时间的锁。因为获取锁的线程显然在获取锁的时候正在执行,所以如果线程持有很短的时间,很有可能该线程还在执行释放锁。

    然而,当涉及 IO 时,自旋锁也可能有效,即当一个线程没有在另一个线程上等待,而是在一个硬件事件发出数据即将到来的信号时,特别是如果该数据很快就会出现(例如等待正在执行的硬件功能)。

    【讨论】:

    • 不是,不是。自旋锁用于 I/O 等待是非常少见的。除了阻塞等待之外,这样的等待通常太长了。驱动程序通常使用信号量来指示 I/O 完成(连同通过内核退出而不是直接中断返回来请求调度运行)。自旋锁仅在锁的持有时间很短的多核系统上提供有效增益,因此减少了争用的可能性以及 CPU/内存带宽的浪费。
    • @MartinJames 这取决于硬件和我们正在讨论的场景。当然,在等待来自远程 Web 服务器的响应时,您是绝对正确的。但是当向板载传感器询问值时,通常使用自旋锁来等待答案。无论如何,我的主要观点不是用于 IO 的自旋锁,而是当自旋锁用于一个等待另一个线程的线程时,OP 正确地指出,需要释放的线程完全是概率问题lock 确实在另一个内核上执行。
    【解决方案2】:

    线程上下文切换的成本是自旋锁有用的原因。对于 Windows 上的开关,引用的通常数字在 2000 到 10,000 个 cpu 周期之间。与必须存储和重新加载处理器状态以及由于保证的高速缓存未命中而导致的停顿相关的成本。这纯粹是开销,没有做任何有用的事情。

    因此,如果一个程序等待一个锁可用,它会消耗数千个周期并定期尝试进入锁,它可以执行得更好。如果期望锁很快变得可用,这可以避免上下文切换。

    没有计时器可用于等待如此短的持续时间,它是通过使用小循环实际燃烧循环来实现的。纺纱。这在处理器级别得到支持,专用的 PAUSE 机器代码指令可用于降低在 Intel/AMD 内核上旋转时的功耗。 .NET 中的 Thread.Yield() 和 Thread.SpinWait() 充分利用了它。

    实际上在代码中有效地使用自旋锁可能会很棘手,当然只有在获得锁的几率足够高的情况下才能正常工作。如果它们不是,那么自旋锁是有害的,因为它会延迟上下文切换,这可能需要让另一个线程重新获得处理器并释放锁。 .NET 4.0 SpinLock 类很有用,它为失败的旋转生成ETW events。否则well documented.

    【讨论】:

    • 仍然不清楚是否存在一些特殊机制来将互锁线程调度到不同的内核。让两个线程在两个核心的 CPU 上竞争资源。如果两个线程都在同一个核心上运行,那么旋转完全浪费了 50% 的等待时间。因此,对于每种特定情况,核心的阈值数量可能存在,当旋转是平均保证胜利时,否则效率低下。如果我的猜测正确,那么代码应该足够聪明,可以根据硬件选择锁定策略。如果 CLR 在单处理器系统上运行,是否有任何回退到通常的锁定?
    • 如果你从根本上弄错了,你将没有什么收获,你永远不应该启动比你拥有的内核更多的线程。 ThreadPool 已经在积极推行的策略。 Thread.SpinWait() 和 SpinLock 类都不会在单处理器系统上旋转。
    • 无论如何,有数千个正在运行的线程共享少量内核。我发现 100 和 101 线程之间几乎没有区别。我错过了什么吗?
    • 如果你的程序启动了数千个线程,那么你就非常错了。整个操作系统通常管理一千个线程。都被屏蔽了。
    • 如果机器有很多进程在烧核,那么你肯定会注意到,你的程序变慢了。当然,这不是您可以通过软件解决的问题,您可以通过获得更好的机器或将昂贵的流程转移到另一台机器来解决它。
    猜你喜欢
    • 2020-12-27
    • 2010-12-29
    • 2012-08-09
    • 2014-07-09
    • 2020-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多