自旋锁与互斥锁

【同步/锁/volatile】 专栏收录该内容
27 篇文章 0 订阅
转载自:http://ifeve.com/practice-of-using-spinlock-instead-of-mutex/

       自旋锁和互斥锁是多线程程序中的重要概念。它们被用来锁住一些共享资源,以防止并发访问这些共享数据时可能导致的数据不一致问题。但是它们的不同之处在哪里?
       从理论上说,如果一个线程尝试加锁一个互斥锁的时候,因为互斥锁已经被锁住了,这个未获取锁的线程会休眠,一直休眠直到持有锁的线程释放了互斥锁,休眠的线程才会被唤醒。如果一个线程尝试获得一个自旋锁的时候没有成功,该线程会一直尝试加锁直到成功获取锁。
       互斥锁存在的问题是,线程的休眠和唤醒都是相当昂贵的操作,它们需要大量的CPU指令,因此需要花费一些时间。如果互斥量仅仅被锁住很短的一段时间,用来使线程休眠和唤醒线程的时间会比该线程睡眠的时间还长,甚至有可能比不断在自旋锁上轮训的时间还长。自旋锁的问题是,如果自旋锁被持有的时间过长,其它尝试获取自旋锁的线程会一直处于自旋锁的状态,这将非常浪费CPU的执行时间,这时候该线程睡眠会是一个更好的选择。

       在单核/单CPU系统上使用自旋锁是没用的,因为当线程尝试获取自旋锁不成功的时候会一直尝试,这会一直占用CPU,其它线程不可能运行,因为其他线程不能运行,这个锁也就不会被解锁。换句话说,在单核/单CPU的系统上,自旋锁除了浪费时间没有一点好处。这时如果这个线程(记为A)可以休眠,其它线程可以立即运行,因为其它有可能解锁,那么线程A可能在唤醒后继续执行。
       在多核/多CPU的系统上,特别是大量的线程只会短时间的持有锁的时候,在使线程睡眠和唤醒线程上浪费大量的时间,也许会显著降低程序的运行性能。使用自旋锁,线程可以充分利用调度程序分配的时间片(经常阻塞很短的时间,不用休眠,然后马上继续它们的工作了), 以达到更高的处理能力和吞吐量。

       实际上,绝大部分现代的操作系统采用的是混合型互斥锁(hybrid mutexes)和混合型自旋锁(hybrid spinlocks)。
       混合型互斥锁,在多核系统上起初表现的像自旋锁一样,如果一个线程不能获取互斥锁,它不会马上被切换为休眠状态,因为互斥量可能很快就被解锁,所以这种机制会表现的像自旋锁一样。只有在一段时间以后(或者尝试一定次数,或者其他指标)还不能获取锁,它就会被切换为休眠状态。如果运行在单核/单CPU上,这种机制将不会自旋(就像上面解释的, 这种情况自旋没有什么好处)。
       混合型自旋锁,起初表现的和正常自旋锁一样,但是为了避免浪费大量的CPU时间,会有一个折中的策略。这种机制不会把线程切换到休眠态(既然想要使用自旋锁,那么你并不希望这种情况发生),也许会决定放弃这个线程的执行(马上放弃或者等一段时间)并允许其他线程运行,这样提高了自旋锁被解锁的可能性(大多数情况,线程之间的切换操作比使线程休眠而后唤醒它要昂贵,尽管那不是很明显)。

  • 0
    点赞
  • 0
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值