user-0 提问: 旋转锁spinlock 为什么会和优先级有关系

回复:
user: user-1
content: 好帖子啊，mark

user: user-2
content: 引用 5 楼 u012879806 的回复:[quote=引用 4 楼 Idle_ 的回复:] 针对单cpu来说，spinlock当然可以锁死整个机器，只要禁止硬件中断，保证当前线程处于运行中（不管优先级如何）就可以了。调度程序其实可以看成是一个函数，它必须有调用者调用才能进行线程切换，这个调用者可以是硬件中断处理程序，可以是用户代码中调用系统函数的一部分。 那么针对单cpu来说，在执行spinlock等待时它其实是占满cpu在运行变量判断的，没人去调用系统函数，禁止硬件中断后也没有中断处理程序去调度，结果就是系统死锁。  你好 3个问题，再次感谢你的参与回复。  1. 禁止硬件中断,   何止是spinlock会导致死锁，其他用户同步对象或者内核同步对象，都会死锁吧。  2.   用户代码调用系统函数的一部分，  请问： 可以举例吗，比如什么函数？    3. 你这些回复， 方便透露一下，是出自哪本书吗？   我想深入学习一下。   [/quote]  1、是的 2、调用系统函数进内核的部分完成功能后很多会调用调度函数，比如所以的IO处理函数，比如创建/销毁线程/进程函数等等。 再加上硬件中断函数中也会调用调度函数 3、没看过书，绝大部分知识来自网络和实践，比如当初尝试ring0 hook时需要独占某个资源时就使用了禁止中断然后用自己写的spinlock创建内核线程锁住了所有非当前cpu，我记得网上查资料就用了至少一周，然后对系统了解加深了很多；少部分来自于面对面交流。

user: user-3
content: 《The Intel 64 and IA-32 Architectures Software Developer's Manual》

user: user-4
content: 引用 楼主 u012879806 的回复:核心编程 8.1里有个例子：  BOOL g_fResourceInUse  = FALSE; void fun1() { while(interlockedexchange(&g_fResourceInUse, true) == true) sleep(0); //access  ...  //no longer need to access interlockedexchange(&g_fResourceInUse,false); }   作者在这个例子后面，加了2段话；  You must take extreme care when using this technique because a spinlock wastes CPU time. The CPU must constantly compare two values until one "magically" changes because of another thread. Also, this code assumes that all threads using the spinlock run at the same priority level. You might also want to disable thread priority boosting (by calling SetProcessPriorityBoost or SetThreadPriorityBoost) for threads that execute spinlocks  问题1： 旋转锁和优先级有什么关系？  作者在这里提是什么用意？     You should avoid using spinlocks on single-CPU machines. If a thread is spinning, it's wasting precious CPU time, which prevents the other thread from changing the value. My use of Sleep in the while loop shown earlier improves this situation somewhat. If you use Sleep, you might want to sleep a random amount of time, and each time the request to access the resource is denied, you might want to increase the sleep time even more. This prevents threads from simply wasting CPU time. Depending on your situation, it might be better to remove the call to Sleep altogether. Or you might want to replace it with a call to SwitchToThread. I hate to say it, but trial and error might be your best approach.  问题2： 在单核上，为什么会阻扰另一个线程去修改锁的值。 先回答你第2个问题,单核,更确切说是单线程cpu,自旋锁的意义就是为了禁止抢占,典型的场景就是,一段数据结构描绘了vip和非vip用户,想象一下查询线程如果准备要查询指定的id是否为vip,这时候管理线程删掉了该id的vip权限,free了该id的vip数据,会有什么样的后果?  多线程并发而造成数据IO冲突在多核cpu的时代,这个问题不像以前禁用抢占那么简单就能完成了.所以才会出现spinlock系列函数.  spinlock 不能锁住软中断,硬中断,也就是说,处于spinlock状态的cpu核心可以被irq,sirq打断,从而使锁失效,假如你的数据正好被中断使用,这时候对数据的IO你并不能保证唯一性. 所以就有spin_lock_bh和spin_lock_irq.以及他们的延生,这2个可以锁软中断,后者是最严格的锁,硬中断一起锁上.

user: user-3
content: 些微膜拜一下Idle_

user: user-0
content: 引用 4 楼 Idle_ 的回复:针对单cpu来说，spinlock当然可以锁死整个机器，只要禁止硬件中断，保证当前线程处于运行中（不管优先级如何）就可以了。调度程序其实可以看成是一个函数，它必须有调用者调用才能进行线程切换，这个调用者可以是硬件中断处理程序，可以是用户代码中调用系统函数的一部分。 那么针对单cpu来说，在执行spinlock等待时它其实是占满cpu在运行变量判断的，没人去调用系统函数，禁止硬件中断后也没有中断处理程序去调度，结果就是系统死锁。  你好 3个问题，再次感谢你的参与回复。  1. 禁止硬件中断,   何止是spinlock会导致死锁，其他用户同步对象或者内核同步对象，都会死锁吧。  2.   用户代码调用系统函数的一部分，  请问： 可以举例吗，比如什么函数？    3. 你这些回复， 方便透露一下，是出自哪本书吗？   我想深入学习一下。

user: user-2
content: 针对单cpu来说，spinlock当然可以锁死整个机器，只要禁止硬件中断，保证当前线程处于运行中（不管优先级如何）就可以了。调度程序其实可以看成是一个函数，它必须有调用者调用才能进行线程切换，这个调用者可以是硬件中断处理程序，可以是用户代码中调用系统函数的一部分。 那么针对单cpu来说，在执行spinlock等待时它其实是占满cpu在运行变量判断的，没人去调用系统函数，禁止硬件中断后也没有中断处理程序去调度，结果就是系统死锁。

user: user-0
content: 引用 2 楼 Idle_ 的回复:spinlock说白了就是一个死循环判断某值是否改变直到其它线程改变这个变量的值才能退出循环。那么对等待的这个线程来说它就是在反复判断某个值，所以分配给它的cpu时间等于是浪费了。如果这个线程是最高优先级的话那么就意味着没有线程可以抢占它的cpu时间，因此也没有线程可以执行代码修改这个lock，最后结果就是所有cpu指令都是判断lock值，整个系统死锁。 如果有比它更高优先级的线程的话，在硬件中断的处理中（比如系统时钟中断）调度程序会暂停现有线程然后切换到那个更高优先级的线程去执行。因此spinlock和线程优先级有极大的关系，即使没有更高优先级的线程，调度程序也会轮流切换到相同优先级的线程中，这个切换的判断条件就是分配给当前线程的cpu时间片，由此可见对单核cpu来说，如果当前线程正在执行spinlock的等待，那么在它时间片用完前，调度程序不会主动切换到其它线程（除非有更高优先级的线程或某个等待线程中有更高优先级的任务在等待cpu），而这个时间片的cpu时间则是完全浪费的（因为它只是在判断某个变量的值）。  大神，看的出来你很有研究。   1. 操作系统会打破优先级逆转的现象，  不知道你对这个了解不，不了解的话，我贴段英文给你： Another situation causes the system to dynamically boost a thread's priority level. Imagine a priority 4 thread that is ready to run but cannot because a priority 8 thread is constantly schedulable. In this scenario, the priority 4 thread is being starved of CPU time. When the system detects that a thread has been starved of CPU time for about three to four seconds, it dynamically boosts the starving thread's priority to 15 and allows that thread to run for twice its time quantum. When the double time quantum expires, the thread's priority immediately returns to its base priority.   操作系统会动态提升优先级，请参考7.10.1  如果你赞同我的说法，那么就会质疑 spinlock是不会死锁。  2.单核cpu的问题，  只能说 在等待线程的某个时间片是浪费的， 但不能说，其他线程（同级或者低优先级线程）没有机会去  修改 某个值。  是有机会的。 作者在书本里的表述有些含糊，让人误解为，单核cpu会导致其他线程（同级或者低优先级的线程）永远没有机会去修改。    我有些疑问：

user: user-2
content: spinlock说白了就是一个死循环判断某值是否改变直到其它线程改变这个变量的值才能退出循环。那么对等待的这个线程来说它就是在反复判断某个值，所以分配给它的cpu时间等于是浪费了。如果这个线程是最高优先级的话那么就意味着没有线程可以抢占它的cpu时间，因此也没有线程可以执行代码修改这个lock，最后结果就是所有cpu指令都是判断lock值，整个系统死锁。 如果有比它更高优先级的线程的话，在硬件中断的处理中（比如系统时钟中断）调度程序会暂停现有线程然后切换到那个更高优先级的线程去执行。因此spinlock和线程优先级有极大的关系，即使没有更高优先级的线程，调度程序也会轮流切换到相同优先级的线程中，这个切换的判断条件就是分配给当前线程的cpu时间片，由此可见对单核cpu来说，如果当前线程正在执行spinlock的等待，那么在它时间片用完前，调度程序不会主动切换到其它线程（除非有更高优先级的线程或某个等待线程中有更高优先级的任务在等待cpu），而这个时间片的cpu时间则是完全浪费的（因为它只是在判断某个变量的值）。

user: user-3
content: 这个问题涉及操作系统内部实现。 可参考Linux源代码中相关内容。