【问题标题】:Why spinlocks don't work in uniprocessor (unicore) systems?为什么自旋锁在单处理器(unicore)系统中不起作用?
【发布时间】:2012-02-28 07:43:01
【问题描述】:

我知道自旋锁与自旋一起工作,存在不同的内核路径并且内核是抢占式的,那么为什么自旋锁在单处理器系统中不起作用? (例如,在 Linux 中)

【问题讨论】:

标签: linux-kernel spinlock


【解决方案1】:

如果我理解您的问题,您是在问为什么自旋锁在单核机器上不是一个好主意。

它们应该仍然工作,但可能比真正的线程休眠并发更昂贵:

当您使用自旋锁时,您实际上是在断言您认为您不必等待很长时间。你是说你认为用繁忙的循环来维护处理器时间片比让你的线程休眠和上下文转移到另一个线程或进程的成本更好。如果您必须等待很短的时间,您几乎可以立即入睡并被重新唤醒,但上下楼的成本比只是等待更昂贵。

这在多核处理器上更可行,因为它们的并发配置文件比单核处理器好得多。在多核处理器上,在循环迭代之间,其他一些线程可能已经处理了您的先决条件。在单核处理器上,其他人不可能帮助你——你锁定了唯一的核心。

这里的问题是,如果你等待或睡在一个锁上,你暗示系统你还没有你需要的一切,所以它应该去做一些其他的事情,然后再回来找你。使用自旋锁,你永远告诉系统这个,所以你锁定它等待其他事情发生 - 但与此同时,你阻止了整个系统 ,所以其他事情不可能发生。

【讨论】:

  • 一个问题:为什么某些线程会在单核系统中休眠/忙碌等待锁定?你说想要进入临界区的线程提示系统说它没有它正在寻找的东西!那还有谁呢? 这是单处理器系统,持有自旋锁的线程永远不会被抢占。因此,如果这个线程正在等待某个东西,是否其他线程在这个“东西”上具有互斥锁并被抢占? 否则,线程总是会得到它想要的东西,我们可以单独使用自旋锁和策略: 中断被禁用,如果持有锁则不抢占。
【解决方案2】:

自旋锁的本质是它不会取消进程调度 - 而是自旋直到进程获得锁。

在单处理器上,它要么立即获得锁,要么永远旋转——如果锁被争用,那么当前持有资源的进程将永远没有机会放弃它。自旋锁只有在另一个进程可以在一个正在旋转的锁上执行时才有用 - 这意味着多处理器系统。

【讨论】:

  • Caf,我在这里有点困惑。 > 你只有一个处理器,当那个处理器试图持有自旋锁时,它会立即获取它。由于您采用了自旋锁,因此无法取消调度。所以现在没有其他进程能够执行。但是,你有提到争执是可能的吗?当您在这里说争用时,您的意思是进程上下文和中断上下文之间的争用?一旦获得自旋锁,其他进程将无法执行?
  • @kumar:没错——如果持有自旋锁的进程被中断并且中断尝试获取相同的锁。
【解决方案3】:

自旋锁有不同的版本:

spin_lock_irqsave(&xxx_lock, flags);
... critical section here ..
spin_unlock_irqrestore(&xxx_lock, flags);

在 Uni 处理器中,当数据需要在进程上下文和中断上下文之间共享时,应该使用 spin_lock_irqsave(),因为在这种情况下 IRQ 也会被禁用。 spin_lock_irqsave() 在所有情况下都可以工作,但部分因为它们是安全的,它们也相当慢。 但是,如果需要跨不同 CPU 保护数据,那么最好使用以下版本,因为在这种情况下不会禁用 IRQ,因此这些版本更便宜:

spin_lock(&lock);
...
spin_unlock(&lock);

在单处理器系统中调用spin_lock_irqsave(&xxx_lock, flags); 与禁用中断具有相同的效果,这将提供所需的中断并发保护而无需不必要的 SMP 保护。但是,在多处理器系统中,这涵盖了中断和 SMP 并发问题。

【讨论】:

    【解决方案4】:

    从本质上讲,自旋锁旨在用于多处理器系统,尽管就并发性而言,运行抢占式内核的单处理器工作站的行为类似于 SMP。如果一个非抢占式单处理器系统曾经在锁上自旋,它将永远自旋;没有其他线程能够获得 CPU 来释放锁。出于这个原因,没有启用抢占的单处理器系统上的自旋锁操作被优化为什么都不做,除了那些改变 IRQ 屏蔽状态的操作。由于抢占,即使您从未期望您的代码在 SMP 系统上运行,您仍然需要实现适当的锁定。

    参考:Linux 设备驱动程序 作者:Jonathan Corbet、Alessandro Rubini、Greg Kroah-Hartma

    【讨论】:

      【解决方案5】:

      操作系统三个简单的部分中找到以下两段可能会有所帮助:

      对于自旋锁,在单 CPU 的情况下,性能开销可能是 相当痛苦;想象一下持有锁的线程是这样的情况 在临界区被抢占。然后调度程序可能会运行 每隔一个线程(想象有 N - 1 个其他线程),每个线程 尝试获取锁。在这种情况下,这些线程中的每一个都将 在放弃 CPU 之前旋转一个时间片的持续时间,a 浪费 CPU 周期。

      但是,在多个 CPU 上,自旋锁可以工作 相当好(如果线程数大致等于 CPU)。思路如下:想象 CPU 1 上的线程 A 和 CPU 2 上的线程 B,两者都在争夺锁。如果线程 A (CPU 1) 抓住锁,然后线程 B 尝试,B 将旋转(在 CPU 2 上)。 然而,大概关键部分很短,因此很快 锁变得可用,并被线程 B 获取。 等待另一个处理器持有的锁不会浪费很多周期 这种情况,因此可以有效

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-12-20
        • 1970-01-01
        • 2014-10-18
        • 1970-01-01
        • 1970-01-01
        • 2015-01-17
        • 2017-09-12
        相关资源
        最近更新 更多