多线程方式下,为了防止竞态,对共享资源加锁是一件很常见的情况.那么在对未抢到锁的线程的处理上,有两种方式:
- 线程挂起,CPU保存上下文,切换到其他线程继续运行;当锁可用时,再唤起线程.线程挂起的时候,CPU可以做其他事情
- 线程不会挂起,CPU一直运行来循环询问锁是否可用
第一种方式叫做互斥锁,第二种方式叫做自旋锁**
这两种方式各自有什么特点呢
- 互斥锁的使用涉及到线程的切换,CPU做线程挂起和唤醒的过程中,上下文切换会耗费巨大的资源
- 自旋锁在未获取到锁的时候会一直循环询问,CPU不能让出,浪费CPU时间
因此很明显我们可以知道
- 使用锁的频率很高的时候,使用互斥锁会非常频繁的进行线程的挂起和唤醒,但使用自旋锁不会
- 持有锁的时间很长的时候,使用自旋锁会导致CPU长时间的占用,但使用互斥锁不会
所以,对于持有锁时间短但使用频率很高的情况,使用自旋锁好过互斥锁;其他一般情况下,还是使用互斥锁吧.
另外,自旋锁还有一个不同于互斥锁的特性--在保持期间不能被抢占.这是什么意思呢?比如说,一个获取到互斥锁的线程被挂起的时候,其他线程是可以获取到这个锁的;而自旋锁不行.
这就意味着使用自旋锁的时候必须要注意
- 在自旋锁释放之前,持有自旋锁的线程一定不能调用sleep.因为sleep会引发内核的线程调度,持有自旋锁的线程挂起,会导致其他线程永远获取不到自旋锁,导致死锁
网友评论