【问题标题】:What guarantee thread with spin lock on multiprocessor run on a different processor什么保证多处理器上具有自旋锁的线程在不同的处理器上运行
【发布时间】:2014-10-14 01:40:59
【问题描述】:

我知道自旋锁只适用于多处理器。但是,如果两个线程试图获取相同的资源并且一个被置于自旋锁上,那么是什么阻止另一个线程不在同一个处理器上运行呢?如果发生这种情况,带有自旋锁的那个将阻止持有资源的那个超出。在这种情况下,它变成了死锁。操作系统如何防止它发生?

【问题讨论】:

    标签: multithreading operating-system spinlock


    【解决方案1】:

    首先介绍一些背景事实:

    • 自旋锁(和一般的锁)不限于多处理器系统。它们在单处理器上运行良好,甚至单线程应用程序也可以使用它们而不会造成任何伤害。
    • 自旋锁不仅由操作系统提供,它们还具有纯用户空间实现。例如, 提供 tbb::spin_mutex
    • 默认情况下,没有什么可以阻止线程在任何可用 CPU 上运行(无论它们使用何种锁)。
    • 有可重入/递归类型的锁。这意味着如果一个线程获得它一次,并试图再次获得它而不释放它,它将成功,而不是像通常的锁那样死锁。但这并不意味着仅仅因为它们被调度到同一个 CPU 就适用于不同的线程。对于任何类型的锁,如果一个软件线程锁定了一个互斥锁,其他线程必须等待。

    一个线程有可能在释放锁之前获得锁并被抢占(即被操作系统计时器中断)。另一个线程可以调度到同一个 CPU,它可能想要获取同一个锁。在纯自旋锁的情况下,该线程将无用地自旋,直到超过操作系统允许的时间片并被抢占。最后,第一个线程将有机会运行并释放它的锁,以便另一个线程能够获取它。

    如您所见,将时间花在绝望的等待上效率并不高。因此,更复杂的实现,在多次尝试获取自旋锁后,调用 OS 寻求帮助,以便自愿将其时间片交给其他可能解锁当前线程的线程。

    【讨论】:

    • 谢谢安东!正如您所说,单处理器的自旋锁有效但无效。在多核系统上,一个线程自旋等待另一个线程运行以释放锁更有意义。如果其他线程没有运行,最好使用互斥锁。它是 Solaris 中的自适应互斥锁。如果我在多处理器系统上使用自旋锁时没有像 Solaris 这样的操作系统,我想用户有责任检查持有锁的另一个线程没有在同一个核心上运行或处于睡眠状态。因为如果是这种情况,互斥锁会更有效。
    • pthread_mutex 在 Linux 上也是自适应的(至少):它首先尝试锁定用户模式,然后进入操作系统。正如我所说,如果多次尝试后仍未获得锁,则自旋锁可以调用操作系统。检查另一个线程的状态似乎很繁重,并且可能无论如何都会调用操作系统,这会破坏自旋锁的好处。
    • 我怀疑那里有任何严重的互斥锁实现不会旋转几个周期左右。内核调用代价高昂,而且大多数锁都是无争用的。 Windows 临界区也是如此。同样,我怀疑您是否可以从用户代码中检查其他线程的状态,因此这样做“优化”将首先消除自旋锁的所有原因。
    • @user2900385,如果有帮助,您可能想要接受/投票,谢谢:)
    猜你喜欢
    • 1970-01-01
    • 2012-05-06
    • 1970-01-01
    • 1970-01-01
    • 2020-02-26
    • 2015-12-29
    • 1970-01-01
    • 2010-11-01
    • 1970-01-01
    相关资源
    最近更新 更多