c - 为什么持有自旋锁时不允许 "sleeping"?

标签 c synchronization linux-kernel sleep spinlock

<分区>

Possible Duplicate:
Why can't you sleep while holding spinlock?

据我所知,自旋锁应该在短时间内使用,并且只是在不允许休眠(抢占)的中断处理程序等代码中的选择。

但是,我不知道为什么会有这样的“规则”,即持有自旋锁时根本不应该休眠。我知道这不是推荐的做法(因为它不利于性能),但我看不出为什么在自旋锁中不应该允许 sleep 。

You cannot hold a spin lock while you acquire a semaphore, because you might have to sleep while waiting for the semaphore, and you cannot sleep while holding a spin lock (from "Linux Kernel Development" by Robert Love).

我能看到的唯一原因是出于可移植性的原因,因为在单处理器中,自旋锁被实现为禁用中断,通过禁用中断,休眠当然是不允许的(但休眠不会破坏 SMP 系统中的代码)。

但我想知道我的推理是否正确,或者是否还有其他原因。

最佳答案

至少在 Linux 中,不允许在自旋锁中休眠有几个原因:

  1. 如果线程 A 在自旋锁中休眠,然后线程 B 试图获取同一个自旋锁,则单处理器系统将死锁。线程 B 永远不会进入休眠状态(因为自旋锁没有必要的等待列表来在 A 完成时唤醒 B),并且线程 A 永远没有机会唤醒。
  2. 使用自旋锁而不是信号量正是因为它们更高效 - 前提是您不会长期争用。允许休眠意味着您将有很长的争用期,从而消除了使用自旋锁的所有好处。在这种情况下,只要使用信号量,您的系统就会更快。
  3. 自旋锁通常用于通过另外禁用中断来与中断处理程序同步。如果您处于 sleep 状态,则此用例是不可能的(一旦您进入中断处理程序,您就无法切换回线程以让它醒来并完成其自旋锁临界区)。

为正确的工作使用正确的工具 - 如果您需要 sleep ,信号量和互斥锁就是您的 friend 。

关于c - 为什么持有自旋锁时不允许 "sleeping"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7868235/

相关文章:

git - 只下载或克隆 git 中的一个分支,而不是整个树

linux - Initramfs : ERROR: Bad version passed vmlinuz-5. 15.36

java - 如何在 JNI 中将 Java 长对象传递给 C

c - 设置字符串为 NULL

android - AccountManager blockingGetAuthToken 卡住了

mercurial - 多二进制文件同步

MySQL 与主数据库同步

c - Hook SIGSEGV 时强制内核转储进程

c - 为什么不能使用 $ 识别 Makefile 中规则的右侧?

单链表上的 C 程序返回错误