背景
了解下自旋锁的知识点
自旋锁
我的印象中主要是为了防止资源竞争时,避免线程切换上下文浪费时间片,而使用的一种锁,它的目的就是保证短时间内能够竞争到资源,避免时间片浪费而提升性能。
但我一直有个疑问,不释放时间片,难道一直死循环吗?这也太不优雅了吧?
看了下ngx的源码
1 | void |
其中涉及到原子操作、cpu_pause、和sched_yield 方法。
原子操作
主要是指cas的原子操作 CAS操作——Compare & Set,或是 Compare & Swap,现在几乎所有的CPU指令都支持CAS的原子操作。 没有这个原子指令,很多功能都完成不了。
- GCC的CAS
1 | GCC4.1+版本中支持CAS的原子操作(完整的原子操作可参看 GCC Atomic Builtins) |
- Windows的CAS
1 | 在Windows下,你可以使用下面的Windows API来完成CAS:(完整的Windows原子操作可参看MSDN的InterLocked Functions) |
- C++11中的CAS
1 | C++11中的STL中的atomic类的函数可以让你跨平台。(完整的C++11的原子操作可参看 Atomic Operation Library) |
cpu_pause
具体说明看链接
主要是两个功能
在循环过程中,避免内存顺序违规导致性能下降
循环等待时,降低cpu功耗
boost 跨平台实现
1 | BOOST_FORCEINLINE void pause() BOOST_NOEXCEPT |
sched_yield
暂时的让出时间片 ,一般都是 usleep/Sleep(0) 或 usleep/Sleep(1) 或 cpu_pause 。
我们自己需要实现自旋锁吗
不需要。2009年linux内核已经把 mutex修改成了自适应锁:
一阶段使用自旋锁,在忙等待一段时间后,若还不能获得锁,则转变成普通锁
二阶段普通锁:阻塞线程
使用c++11 std::mutex 也有相同的性能。 实际测试中, std::mutex 比windows的 CRITICAL_SECTION 还是有10%左右的性能提升。