Spinlock(自旋锁)和mutex作为两种互斥锁,在并行编程中都得到了广泛应用。那么,这两种锁有什么区别吗?
当一个线程对Spinlock加锁时,如果该锁被其他线程占用,那么该线程会通过一个loop不断地重试( try again and again);而使用mutex的线程没有得到锁时,会sleep。
因为,当临界区较短时,Spinlock因为没有上下文切换,可能性能更优;当临界区较长时,不断的spin将浪费大量的cpu资源。
如何实现一个Spinlock呢?下面简单封装了一下,并在Ubuntu 14.04 32bit系统,X86体系结构,Intel I5双核处理器环境下,测试相应的性能:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
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的要多。
小结
以下两种情况,应该考虑使用spinlock代替mutex:
1,每个processor上(只)运行一个线程。
2,线程平均等待(spin)时间少于两次上下文切换的开销。
当然,一切都离不开实际的测试和分析。
下次,我们将研究更多、更高效的spinlock实现。