百科问答小站 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++20 即将到来的 coroutine 能否与 Golang 的 goroutine 媲美? 
  如何修改shared_ptr智能指针,让他支持多线程? 
  qt5.5中给全零地址发送udp数据包为何会失败? 
  关于 C++ 顶层 const 和底层 const? 
  malloc申请的内存能是虚拟内存吗,也就是申请的一块新的空间,刚申请就缺页吗? 
  如果让你来重新设计(或者改造)C++,你打算怎么设计或者修改? 
  Linus Torvalds 的 C++ 水平如何,为什么他敢炮轰此编程语言? 
  C 语言这些宏定义前面的 __extension__ 是什么意思? 
  C++ 运动完上一个函数到下一个函数时,上一个函数里的变量值(结构体变量)为什么没保留住,变成零了? 
  C++ 的 switch 为什么不自动加 break? 

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





© 2025-04-16 - tinynew.org. All Rights Reserved.
© 2025-04-16 - tinynew.org. 保留所有权利