Linux内核中的互斥锁和自旋锁的区别

很多人搞不清自旋锁和互斥锁的区别,这两种锁都是最底层的锁实现。是很多高级锁的基础。
为什么需要锁?
共享资源是有限的,且同一时间只能有一方占用。就像我们常见的共享单车,它是多人共用的,但是在某个时刻,只能有一个人使用,当我们扫码的时候,它只属于我们,其他人不能占用。这就是加锁的意义。为了保证系统中的共享资源在一个时刻只能有一个线程访问,避免多线程同时使用导致的数据错乱。
锁是谁加的?
任何操作都是由内核完成,线程向内核申请加锁,是否能锁住是由内核决定的。

互斥锁

假设我们目前有两个进程,进程A和进程B。当A需要枷锁的时候会向内核申请获取锁,获取成功后独占互斥锁,进行自己的任务执行。此时B想要获取锁,但此时锁被A占用,所以获取失败,内核将现成B置为休眠状态。等到进程A执行完毕释放锁之后,内核在核实的时机唤醒进程B,成功获取锁后继续执行。
在这里插入图片描述
https://blog.csdn.net/qq_37935909/article/details/108625508
需要注意的是在进程B加锁失败后,会从用户态陷入内核态,让内核切换线程,简化了使用锁的难度,但是对性能存在影响。
当两个线程属于同一个进程,因为内存是共享的,所以在切换时虚拟内存这些资源保持不动,只切换线程的私有数据、寄存器等不共享的数据。
上下文的切换耗时比较短,只有几十纳秒到几微秒。如果加锁部分运行的代码比较短,有可能上下文切换的时间比锁住的代码时间还长,就得不偿失了,所以当确定被锁住的代码部分执行时间比较短,就不适合实用互斥锁,应该选择自旋锁。

自旋锁

自旋锁其核心是使用CPU的CAS,在用户态完成加锁和解锁,不会主动产生线程上下文切换,所以比互斥锁来说,时间上会快很多。同时自旋锁不需要线程休眠,对资源的开销也更小。
使用自旋锁的时候,当发生多线程竞争锁的情况,加锁失败的线程会忙等待,直到拿到锁。忙等待可以通过while循环实现,不过最好是使用CPU提供的PAUSE指令来实现。
自旋锁利用CPU周期一直自旋直到锁可用。由于一个自选的线程永远不会放弃CPU,因此在单核CPU上,需要抢占式的调度器(不断通过时钟中断一个线程,运行其他线程)。
自旋的时间和被锁住的代码执行的时间成正比关系。
所以选择互斥锁还是自旋锁,要根据实际情况来看。一些更高级的锁会选择其中一个来实现。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值