百科问答小站 logo
百科问答小站 font logo



如何设计真正高性能的 spin_lock? 第1页

  

user avatar   skywind3000 网友的相关建议: 
      

应用层用spinlock的最大问题是不能跟kernel一样的关中断(cli/sti),假设并发稍微多点,线程1在lock之后unlock之前发生了时钟中断,一段时间后才会被切回来调用unlock,那么这段时间中另一个调用lock的线程不就得空跑while了?这才是最浪费cpu时间的地方。所以不能关中断就只能sleep了,怎么着都存在巨大的冲突代价。

尤其是多核的时候,假设 Kernel 中任务1跑在 cpu1上,任务 2跑在 cpu2上,任务1进入lock之前就把中断关闭了,不会被切走,调用unlock的时候,不会花费多少时间,cpu2上的任务2在那循环也只会空跑几个指令周期。

看看 Kernel 的 spinlock:

                #define _spin_lock_irq(lock)           do {            local_irq_disable();            preempt_disable();            _raw_spin_lock(lock);            __acquire(lock);           } while (0)             

看到里面的 local_irq_disable() 了么?实现如下:

        #define local_irq_disable()  __asm__ __volatile__("cli": : :"memory")       

倘若不关闭中断,任务1在进入临界区的时候被切换走了,50ms以后才能被切换回来,即使原来临界区的代码只需要0.001ms就跑完了,可cpu2上的任务2还会在while那里干耗50ms,所以不能禁止中断的话只能用 sleep来避免空跑while浪费性能。

所以不能关闭中断的应用层 spinlock 是残废的,nop都没大用。

不要觉得mutex有多慢,现在的 mutex实现,都带 CAS,首先会在应用层检测冲突,没冲突的话根本不会不会切换到内核态,直接用户态就搞定了,即时有冲突也会先尝试spinlock一样的 try 几次(有限次数),不行再进入休眠队列。比傻傻 while 下去强多了。




  

相关话题

  简单c++项目在Windows和Linux下编译连接怎样使用同一个Makefile? 
  C++ 中 new 和定位 new 的返回值都是 void*,却为什么可以被赋值给不同类型的指针? 
  C++解析xml有什么好用的轮子? 
  为何C++11与1y都没有将network功能优先加入标准库? 
  C++ 语言会不会在十年内退出市场? 
  C++的CRTP所带来的静态多态功能具体有什么用? 
  编译器是如何实现C/C++中的const的功能? 
  C++中 int n = 0ULL - 1; 是 UB 未定义行为吗? 
  C++20有哪些让你激动不已的新特性? 
  intel x86指令编码存在多个选择时如何选定opcode? 

前一个讨论
如果一个程序员工作5年后还没成为大牛,是不是该考虑别的路子了?
下一个讨论
进体制是普通人规避中年危机的最佳方式吗?





© 2025-06-19 - tinynew.org. All Rights Reserved.
© 2025-06-19 - tinynew.org. 保留所有权利