百科问答小站 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 下去强多了。




  

相关话题

  GCC 4 编译警告:warning: dereferencing type-punned pointer will break strict-aliasing rules 有什么比较好的解决办法? 
  PHP、Java、Python、C、C++ 这几种编程语言都各有什么特点或优点? 
  C++ 父类对象赋值给子类对象是未定义行为么? 
  C++开发只能去大厂吗? 
  C++中 union 储存的 char 成员能否通过 int 成员读取? 
  C++ 的 switch 为什么不自动加 break? 
  如果编译器遇到未定义行为把硬盘格式化了,需要负法律责任吗? 
  C++构造函数为什么要依赖初始化列表? 
  Unix网络编程里的阻塞是在操作系统的内核态创建一个线程来死循环吗? 
  C++ 的 switch 为什么不自动加 break? 

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





© 2025-03-31 - tinynew.org. All Rights Reserved.
© 2025-03-31 - tinynew.org. 保留所有权利