ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

自旋锁与互斥锁

2022-05-04 14:00:50  阅读:185  来源: 互联网

标签:locked 获取 互斥 线程 自旋 CPU


前言

在编程中经常需要使用到互斥. 互斥就是, 这个事情只能有一个人干, 我正在做着的时候, 别人要想做这件事就得等我做完了.

互斥的实现是通过锁的机制, 也就是我把这块锁上了, 别人就进不来了, 等我做完再把锁释放掉.

但是, 前辈们已经证明了, 要想单纯的在软件层面上实现锁的机制是很难的, 即使是简单的一条加1的操作, 在CPU执行时也需要如下几步:

  1. 将变量从内存读到寄存器
  2. 寄存器中的值加1
  3. 将寄存器中的值写回内存

而中间任何一步发生切换, 都可能导致锁机制的失败. 因此, 在软件层面的实现代价是很高的(感兴趣的可搜一下: Peterson 算法).

造成其困难的原因是什么呢? 因为无法保证单条 CPU 指令的原子性. 既然软件不够, 那就硬件来凑咯.

于是, CPU提供了lock指令, 可以保证单条指令的原子性. 而有了硬件的支持,锁的实现就简单的多了. 比如在有一条指令xchg用来对两个变量进行交换, 那么就可以将锁放到一个全局变量中, 规定谁换到锁了就持有, 用完再放回去. 很简单的实现了锁的机制. (至于硬件上是如何实现的, 我确实不甚了解, 因此这里按下不表)

好, 现在能够很容易的实现锁了, 但是既然能拿到锁, 那也就有可能拿不到锁. 如果没有拿到锁, 怎么办呢? 两种应对方案既: 自旋/互斥, 他们也是其他锁(读写锁/乐观锁/悲观锁)的底层实现.

自旋锁

在获取锁失败的情况下, 立刻再次尝试获取. 大概这样:

int locked = 0;
void lock() {
    // 将1放入 locked 变量
    // 若 locked 中存放的是 1, 则说明当前已经有其他人获取了, 继续等待
    while (xchg(&locked, 1)) ;
}
void unlock() {
    // 使用完后, 将变量置为0
    xchg(&locked, 0);
}

既, 线程会不停的尝试获取锁.

但是, 忙等会导致如下问题:

  • 线程在空转, 浪费 CPU 性能
  • 争抢锁的线程越多, CPU 的利用率越低
    • 假设有100个线程在争抢锁, 其中一个线程拿到了, 那么剩下99个都在空转
    • 如果抢到锁的线程被操作系统调度走了, 那么剩下的全部线程(99个)都在空转

互斥锁

自旋锁的问题其实就出在忙等上, 假设没有拿到锁的话, 就将线程暂时休眠, 等到锁被释放了再将其唤醒, 这样不就能够避免性能的浪费了嘛.

但是, 线程的调度靠线程自己是无法完成的. 需要操作系统帮忙调度.

既然进行了线程调度, 那必然就需要进行线程的上下文切换了.

但是, 如果锁的占用时间比线程上下文切换的时间还要短呢? 这边线程上下文切换还没完成, 那边锁已经释放了, 这不就会导致运行效率的降低了么.

结合

自旋锁的问题是忙等会浪费 CPU 性能, 而互斥锁的问题是若锁的持有时间极短会导致运行效率的降低.

也就是说

  • 在占有锁的时间较短时, 自旋锁的开销更小. (可以立即获取锁)
  • 在占有锁的时间较长时, 互斥锁的开销更小. (CPU 不用空转)

那么有没有一种既不会浪费 CPU 性能, 又不会降低线程运行效率的办法呢? 有,

  1. 通过自旋尝试获取锁
  2. 若获取失败, 则转为互斥

这样可以令大部分情况在首次获取锁时便能拿到, 无需线程切换. 在较少的情况下, 会造成部分性能的浪费. 但是整体性能是提高了的.

最后, 我们在日常上层开发的时候, 其实很少考虑获取锁的实现方式是自旋还是互斥, 更多考虑的是读写锁还是什么. 底层已经为我们选择了最合适的方式.

标签:locked,获取,互斥,线程,自旋,CPU
来源: https://www.cnblogs.com/hujingnb/p/16220962.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有