很多时候,当一个进程为了等待mutex而刚刚进入睡眠的时候,mutex已经被释放了,如果能在第一时间感知mutex被释放那是再好不过的了,解决该问题的方式就是用自旋忙等而不是阻塞等待,是这样吗?
关于竞态,当初由于不能忍受频繁的睡眠/唤醒而引入了自旋锁,然后又因为自旋锁在实时系统中会导致其它进程长时间延迟造成吞吐量下降而在实时系统中又恢复 了睡眠/唤醒,实时系统中的首要特性不是节省开销,而是保证运行,睡眠/唤醒机制保证了争抢锁的进程不会影响到别的进程从而保证了吞吐量不会被降低,但是 自旋锁用mutex实现的代价是客观存在的,它必须实现优先级继承或者优先级置顶以保证不会发生优先级逆转和死锁,因为现在自旋锁可以睡眠了,而内核又是 可以抢占的,一旦有高优先级的进程就绪,那么它就会抢占低优先级的进程,这是如果低优先级的进程正好持有那一把锁,那么就会被阻塞而不能运行(单cpu或 者进程/cpu绑定的情况),此时一个中间优先级的进程抢占了低优先级的进程,那么这会导致高优先级的进程的阻塞时间过于长,在实时系统中必须避免这种情 况,因此在实时系统内核中,比如linux内核中,就实现了优先级继承协议-PIP,协议的实现引入了大量的数据结构和算法,这就引入了管理开销,这些开 销会抵消掉一部分睡眠/唤醒带来的吞吐量的提高和其它进程延迟的降低,因此,下面的一杆秤就需要在这二者之间拨弄秤砣了。
传统自旋锁的实现保证了自旋锁的持有者不会被打断,这就可以保证即使高优先级的进程被破延迟也只是在自旋,而自旋时间内持有锁的进程会一直运行,而且运行 逻辑一直和这把锁有关,即使它释放了锁之后没有被等待者抢到,那么抢到锁的进程也不会做别的事(在ticket spin lock中这种混乱得到了改善),虽然延迟是有的,但是起码都是在围绕着锁作正经事而不会被别的进程打断,如果你真的在持有自旋锁的时候调用了一个 schedule,那么只能怪写代码的人了。因此传统的自旋锁不用任何开销就可以避免优先级逆转之类的令人难堪的局面,是的,没有任何开销,把抢占一关锁 一占完事,剩下的就尽情执行吧,不会被打扰,然而这样的话虽然避免了优先级逆转带来的争抢锁高优先级的进程延迟但是会引入不争抢锁的所有高优先级进程的延 迟,因为自旋锁简单的关闭了抢占(简单无开销)。因此传统的自旋锁和睡眠/唤醒机制都不适合实时系统,带有优先级继承协议的mutex机制实现的自旋锁是 可以的,但是管理优先级继承协议的数据结构和算法也够呛,这么多的但是降到底如何是好,现在有三种方案实现实时系统自旋锁,第一就是传统自旋锁,第二就是 传统的睡眠/唤醒机制,第三就是实现PIP的mutex机制,前两种都基本没有管理开销但是因为影响系统吞吐量和延迟,第二种还会引入睡眠/唤醒开销,这 导致这两种不能用,第三个方案由于不怎么影响系统延迟但是运行开销很大,运行开销有睡眠/唤醒的开销,管理复杂数据结构和算法的开销。因此,将这三种方案 的优势组合然后避免它们的劣势是最好的结果了,其实这三种方案正交化一下就是:自旋锁,睡眠/唤醒,PIP协议,其中PIP是不可省略的,因此选择自旋锁 的低开销和睡眠/唤醒的高吞吐量,因此结果就是自适应自旋锁,也就是说它会在某些情况下自旋而在另外一些情况下睡眠,这就是它的优势。那么在何种情况下自 旋呢?理想的情况就是自动学习,起初可能会很影响性能,毕竟要学习嘛,多次尝试自旋以后,会得到一些统计值,比如得到锁的平均延迟,平均自旋次数,n次自 旋内得到锁的次数,系统根据这些统计值决定下一次是自旋还是睡眠。然而这种实现合理吗?看似很合理啊,也很智能,几乎不用怎么配置就可以自动运行的很好, 但是想想看,这毕竟是在内核,内核不是秀算法的地方,智能的,复杂的算法还是在用户空间秀比较好,内核算法和数据结构的特征就是简单,高效,因此内核实现 的自适应锁还是要另外开辟新的方案。

转载于:https://blog.51cto.com/dog250/1274144

自适应自旋锁--吞吐量和延迟以及管理开销的折中相关推荐

  1. 互斥锁、自旋锁和自适应自旋锁

    互斥锁: 从 实现原理上来讲,Mutex属于sleep-waiting类型的锁.例如在一个双核的机器上有两个线程(线程A和线程B),它们分别运行在Core0和 Core1上.假设线程A想要通过pthr ...

  2. SMP并行编程为什么这么难-从Linux自旋锁到图灵机

    周末,聊点轻松的话题. 本文通过一个不甚成功的优化自旋锁的半吊子尝试,聊一下操作系统并行的难点,中间的部分,说说图灵机和冯诺伊曼体系. 和往常一样,我的文章对概念的阐述非常少,更多的是一些需要思考的东 ...

  3. java锁结构之自旋锁与适应性自旋锁

    一.为什么需要自旋锁与适应性自旋锁 1.1.自旋锁的提出背景   由于在多处理器环境中某些资源的有限性,有时需要互斥访问,这时候就需要引入锁的概念,只有获取了锁的线程才能对资源进行访问,由于多线程的核 ...

  4. 轻量级锁的加锁和解锁逻辑-自旋锁

    轻量级锁在加锁过程中,用到了自旋锁 所谓自旋,就是指当有另外一个线程来竞争锁时,这个线程会在原地循环等待,而不是把该线程给阻塞,直到那个获得锁的线程释放锁之后,这个线程就可以马上获得锁的. 注意,锁在 ...

  5. 读写自旋锁详解,第 3 部分(来自IBM)

    基于简单共享变量的读写自旋锁的不足 本系列文章的第 2 部分中给出的实现都基于简单共享变量,简洁实用,但在大规模多核.NUMA 系统上可扩展性较差.我们说某个读写自旋锁的实现是可扩展的,通俗地讲是指在 ...

  6. java 自旋锁_搞懂Java中的自旋锁

    轻松搞懂Java中的自旋锁 前言 在之前的文章<一文彻底搞懂面试中常问的各种"锁">中介绍了Java中的各种"锁",可能对于不是很了解这些概念的同学 ...

  7. 轻量级锁_一句话撸完重量级锁、自旋锁、轻量级锁、偏向锁、悲观、乐观锁等各种锁 不看后悔系列...

    重量级锁?自旋锁?自适应自旋锁?轻量级锁?偏向锁?悲观锁?乐观锁?执行一个方法咋这么辛苦,到处都是锁. 今天这篇文章,给大家普及下这些锁究竟是啥,他们的由来,他们之间有啥关系,有啥区别. 重量级锁 如 ...

  8. 自旋锁 轻量锁_Java知识进阶-程序员升往架构师必经之路-自旋锁-知识铺

    知识铺: 致力于打造轻知识点,持续更新每次的知识点较少,阅读不累.不占太多时间,不停的来唤醒你记忆深处的知识点. 一. 锁类型 1.1 乐观锁 Java中CAS操作,就是一种乐观锁,前文也讲过了详细的 ...

  9. java 自旋_java自旋锁的代码实现

    自旋锁:spinlock 是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环耗用CPU import java.util.concurrent ...

最新文章

  1. 写代码做副业月入33K+的方法都藏在这几个淘宝大佬的公众号里!
  2. HTML之垂直居中问题
  3. 华为NIP网络***检测系统
  4. zookeeper的ZAB协议学习
  5. 【技术博客-总览--重要】
  6. 2020国开c语言程序设计1075,代号1253国开点大2017年6月春季学期本科期末考试《C语言程序设计》试题及答案.pdf...
  7. java arraylist length,在Java中调整ArrayList的大小时,无法理解溢出的可能性
  8. 解决NSTimer循环引用
  9. 【图像压缩】基于matlab DCT变换图像压缩【含Matlab源码 804期】
  10. python 模块下载资源汇总
  11. VB.NET2010 编程实现Word双面打印
  12. c语言程序设置存根,gmock可以用于存根C函数吗?
  13. postman 一直Sending
  14. MT6761处理器介绍
  15. lmp+heartbeat+drbd
  16. iOS如何完成蓝牙打印机功能
  17. Altium Designer19(AD19)
  18. 全国计算机等级考试证书电子,全国计算机等级考试证书效力
  19. 伯禹-公益AI学习打卡 Task02
  20. 差序格局与关系取向社会

热门文章

  1. php 去除 bom,PHP批量检测并去除文件BOM头信息代码参考
  2. .net textbox全屏后自适应变大_手机屏幕太小?无套路不花钱变大屏!
  3. nfc修改饭卡软件下载_你还要什么校园卡?有NFC不就够了
  4. java中 object创建对象_java创建对象的几种方式
  5. pytorch保留比较高的epoch的权重
  6. hosts ip 指向ip_不同网段共享打印机?不同IP段怎么共享打印机?
  7. numpy与pandas各种功能及其对比(超全)
  8. YOLOX目标检测模型Keras实现,超越Yolov5
  9. 基于PyTorch+YOLOv4的口罩佩戴检测,附数据集
  10. 百度开源的依存句法分析系统