Spinlock(自旋锁)和mutex作为两种互斥锁,在并行编程中都得到了广泛应用。那么,这两种锁有什么区别吗?
当一个线程对Spinlock加锁时,如果该锁被其他线程占用,那么该线程会通过一个loop不断地重试( try again and again);而使用mutex的线程没有得到锁时,会sleep。
因为,当临界区较短时,Spinlock因为没有上下文切换,可能性能更优;当临界区较长时,不断的spin将浪费大量的cpu资源。
如何实现一个Spinlock呢?下面简单封装了一下,并在Ubuntu 14.04 32bit系统,X86体系结构,Intel I5双核处理器环境下,测试相应的性能:
#include<thread> using namespace std; int counter = 0; int lock = 0; void spin_lock() { while(__sync_lock_test_and_set(&lock, 1)); } void spin_unlock() { __sync_lock_release(&lock); } void f() { for (int i = 0; i < 10000000; i++) { spin_lock(); counter = counter + 2;//tiny critical section spin_unlock(); } } int main() { thread t1(f); thread t2(f); t1.join(); t2.join(); return 0; }
2个线程时,这个程序的运行时间为:
real 0m1.082s user 0m2.060s sys 0m0.000s
4个线程时:
real 0m5.701s user 0m19.400s sys 0m0.000s
如果改为std::mutex(lock和unlock成员函数)呢?对比一下:
2个线程:
real 0m3.081s user 0m2.796s sys 0m3.344s
4个线程:
real 0m5.860s user 0m6.004s sys 0m14.936s
不难发现,由于大量的上下文切换,使用mutex时,花在sys上的时间要远比使用Spinlock的要多。