Lock Convoy(锁封护)


  [1]Lock Convoy是在多线程并发环境下由于锁的使用而引起的性能退化问题。当多个相同优先级的线程频繁地争抢同一个锁时可能会引起lock convoy问题,一般而言,lock convoy并不会像deadlock或livelock那样造成应用逻辑停止不前,相反地,遭受lock convoy的系统或应用程序仍然往前运行,但是,由于线程们频繁地争抢锁而导致过多的线程环境切换,从而使得系统的运行效率大为降低,而且,若存在同等优先级下不参与锁争抢的线程,则它们可以获得相对较多的处理器资源,从而造成系统调度的不公平性。
  Lock Convoy描述的是这样一种情况,假设有ABC三个线程在同一个时间片内多次取锁,在不考虑优先级的情况下(假设调度规则为平均时间),则可能发生当A执行1/3的时间片后被调度进程中断,转而执行B,B也执行了1/3的时间片后被调度进程中断,执行C。这样三个线程总是没执行完时间片就被打断。(在现代操作系统中,只要一个线程获取了一个时间片,那么在时间片内它就不能被重新执行),导致线程频繁切换,而降低系统的执行效率。

除了引起调度粒度变小以外,lock convoy的另一个问题是造成调度器的时间分配不公平。假设另有一个线程X也是在同等的优先级上运行,但没有参与锁竞争。于是,在每一轮的锁竞争过程中,线程X都有机会被分配一次完整的时间片,于是,这些竞争的线程在一轮中获得1/3时间片,而非竞争的线程可以获得完整的时间片。当然,你可以说这种不公平是由于它们抢锁而引起的,但从时间分配比例而言,参与竞争与不参与竞争的线程是不公平的。下图说明了线程X和A、B、C之间的执行时间差异。

  由以上描述可以看出,Lock convoy的存在条件是,参与竞争的线程频繁地获取锁,锁被一个线程释放以后其所有权便落到了另一个线程的手里。在操作系统中,相同优先级的线程按照FIFO的顺序被调度和执行,竞争同一个锁的线程也按照FIFO的顺序被依次成功地获取到锁。这些条件在现代操作系统中都能被满足,包括Windows。

  一种合理的缓解lock convoy的方案,要求在每个线程获取锁的时候先尝试(try),如果尝试多次仍不成功,再阻塞。

 
Priority inversion(优先级反转)

  高优先级任务需要等待低优先级任务释放资源,而低优先级任务又正在等待中等优先级任务的现象,叫做优先级反转。
  (注意: 此时高优先级任务和中等优先级任务之间没有任何共享资源但执行顺序却发生了倒置,这种情况才称为优先级反转;而高优先级任务因为等待低优先级任务释放资源而阻塞的情况则不称为优先级反转。)
 
  图片含义:当低优先级在运行时被高优先级打断,但高优先级所使用的资源被低优先级所占用而阻塞,此时中优先级打断低优先级任务,低优先级任务发生了阻塞,而此时高优先级和中优先级没有任何资源共享,却发生了优先级反转。
 
       两种经典的防止反转的方法:
        1. (Priority inheritance,优先级继承):继承现有被阻塞任务的最高优先级作为其优先级,任务退出临界区,恢复初始优先级。 在上述例子中当高优先级任务需要等待低优先级任务释放资源而阻塞时,就将低优先级任务的优先级升为高优先级任务的优先级,当它退出临界区后就将其优先级恢复为初始优先级。
        2. (Priority ceilings,设置优先级上限):设置优先级上限是指将申请(占有)某资源的任务的优先级提升到可能访问该资源的所有任务中最高优先级任务的优先级。如上面的例子,如果给低优先级线程抬高到最高优先级,那么中级优先级程序就不会被调度,不会发生优先级反转。
 
 
 
 

线程调度的问题:Lock Convoy(锁封护)与Priority Inversion(优先级反转)的更多相关文章

  1. [C#基础]说说lock到底锁谁?

    写在前面 最近一个月一直在弄文件传输组件,其中用到多线程的技术,但有的地方确实需要只能有一个线程来操作,如何才能保证只有一个线程呢?首先想到的就是锁的概念,最近在我们项目组中听的最多的也是锁谁,如何锁 ...

  2. Coarse-Grained lock 粗粒度锁

    用一个锁Lock一组相关的对象 有时,需要按组来修改多个对象. 这样,在需要锁住其中一个的时候,必须连带地将其他的对象都上锁. 为每一个对象都加上一个锁是很繁琐的. 粗粒度锁是覆盖多个对象的单个锁. ...

  3. Java 线程锁机制 -Synchronized Lock 互斥锁 读写锁

    (1)synchronized 是互斥锁: (2)ReentrantLock 顾名思义 :可重入锁 (3)ReadWriteLock :读写锁 读写锁特点: a)多个读者可以同时进行读b)写者必须互斥 ...

  4. JUC--Callable 以及Lock同步锁

    /** * 一.创建执行线程的方式三:实现Callable接口.相较于实现Runnable接口方式,方法可以有返回值,并且可以抛出异常 * 二.callable 需要FutureTask实现类的支持. ...

  5. C# 说说lock到底锁谁?(1)

    写在前面 最近一个月一直在弄文件传输组件,其中用到多线程的技术,但有的地方确实需要只能有一个线程来操作,如何才能保证只有一个线程呢?首先想到的就是锁的概念,最近在我们项目组中听的最多的也是锁谁,如何锁 ...

  6. C# 说说lock到底锁谁?(2)

    摘要 今天在园子里面有园友反馈关于[C#基础]说说lock到底锁谁?文章中lock(this)的问题.后来针对文章中的例子,仔细想了一下,确实不准确,才有了这篇文章的补充,已经对文章中的demo进行修 ...

  7. [C#基础]说说lock到底锁谁?(补充与修改)

    摘要 今天在园子里面有园友反馈关于[C#基础]说说lock到底锁谁?文章中lock(this)的问题.后来针对文章中的例子,仔细想了一下,确实不准确,才有了这篇文章的补充,已经对文章中的demo进行修 ...

  8. spin lock自旋锁 双链表操作(多线程安全)(Ring0)

    通过spin lock自旋锁 ,为每个链表都定义并初始化一个锁,在需要向该链表插入或移除节点时不使用前面介绍的普通函数,而是使用如下方法: ExInterlockedInsertHeadList(&a ...

  9. 多线程安全问题之Lock显示锁

    package com.hls.juc; import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.Reentr ...

随机推荐

  1. TP5之查询那些事

    1.使用 model 查询,查出的类型为 对象 $a 是一个对象,使用 $a->name 的方式来获取 对象里的属性 2.使用 db 查询,查询出的是 数组 $b 是一个数组,使用 $b['na ...

  2. CSS Unicode字体

    在 CSS 中设置字体名称,直接写中文是可以的.但是在文件编码(GB2312.UTF-8 等)不匹配时会产生乱码的错误.xp 系统不支持 类似微软雅黑的中文. 方案一: 你可以使用英文来替代. 比如 ...

  3. lightoj 1027【数学概率】

    #include <bits/stdc++.h> using namespace std; typedef long long LL; const int N=1e2+10; int ma ...

  4. POJ 3067【树状数组】

    题意: 给你两行数字,n个m个,然后给你k条线直接把两个数连起来,问有多少个交叉的 思路: 假定上一行是起点,下一行是终点. 把路按照起点从大到下排序, 然后可以直接对每条路查询,这条路目前的交叉数, ...

  5. bzoj 2406: 矩阵【二分+有源汇上下界可行流】

    最大值最小,所以考虑二分 |Σaij-Σbij|<=mid,所以Σbij的上下界就是(Σaij-mid,Σaij+mid) 考虑建有上下界网络,连接(s,i,Σaik-mid,Σaik+mid) ...

  6. [Xcode 实际操作]八、网络与多线程-(6)使用UIApplication对象打开地图

    目录:[Swift]Xcode实际操作 本文将演示如何使用应用程序单例对象,打开地图的功能. 在项目导航区,打开视图控制器的代码文件[ViewController.swift] import UIKi ...

  7. IT兄弟连 JavaWeb教程 JSP中的三大指令

    指令标识主要用于设定整个JSP页面范围内都有效的相关信息,它是被服务器解释并执行的,不会产生任何内容输出到网页中.也就是说,指令标识对于客户端浏览器是不接见的.JSP页面的指令标识与我们的身份证类似, ...

  8. Java 虚拟机(Java Virtual Machine)

    Java 编译器将 Java 程序编译成虚拟机能够识别的二进制代码,这种代码称为字节码(Bytecode).字节码就是虚拟机的机器指令,它与平台无关,有统一的格式,不依赖于具体的硬件环境,只运行在 J ...

  9. 跳跃表&hash

    汇编刚学跳跃表,发现跳跃表与hash有着数不清的关系 维基百科: 哈希表(哈希映射)是实现关联数组抽象数据类型的数据结构,该结构可以将键映射到值.哈希表使用哈希函数来计算桶或槽阵列的索引,从中可以找到 ...

  10. 最简大数据Spark-2.1.0

    0.0 前言 本文主要基于最新的Spark 2.1.0版本.阅读本文可以对Spark 2.1.0的学习过程,运行流程,关键组件,原理有所了解.文章有点长,你也可以直接阅读感兴趣的部分,但是还是建议全面 ...