所谓公平性指所有线程对临界资源申请访问权限的成功率都一样,不会让某些线程拥有优先权。通过前面的CLH Node FIFO学习知道了等待队列是一个先进先出的队列,那么是否就可以说每条线程获取锁时就是公平的呢?关于公平性这里分拆成三个点分别阐述:

① 准备入队列的节点,此情况讨论的是线程加入等待队列时产生的竞争是否公平,线程在尝试获取锁失败后将被加入等待队列,这时多个线程通过自旋将节点加入队列,所有线程在自旋过程中是无法保证其公平性的,可能后来的线程比早到的先进入队列,所以节点入队列不具公平性。

② 等待队列中的节点,情况①中成功加入队列后即成为等待队列中的节点,我们知道此队列是一个先入先出队列,那么很简单能得到,队列中的所有节点是公平的,他们都按照顺序等待自己被前驱节点唤醒并获取锁,所以等待队列中的节点具有公平性。

③ 闯入的节点,这种情况是指一个新线程到达共享资源边界时不管等待队列中是否存在其他等待节点它都将优先尝试去获取锁,这种称为可闯入策略。可闯入特性破坏了公平性,AQS框架对外体现的公平性主要由此体现,下面将对闯入特性展开分析。

AQS提供的基础获取锁算法是一种可闯入的算法,即如果有新线程到来先进行一次获取尝试,不成功的情况下才将当前线程加入等待队列。如图2-5-9-6所示,等待队列中节点线程按照顺序一个接一个尝试去获取共享资源的使用权,某时刻头结点线程准备尝试获取的同时另外一条线程闯入,此线程并非直接加入等待队列的尾部,而是先跟头结点线程竞争获取资源,闯入线程如果成功获取共享资源则直接执行,头结点线程则继续等待下一次尝试,如此一来闯入线程成功插队,后来的线程比早到的线程先执行,说明AQS基础获取算法是不严格公平的。

 

图2-5-9-6 闯入线程

基础获取算法逻辑简化如下:首先尝试获取锁,假如获取失败才创建节点并加入到等待队列的尾部,接着通过不断循环检查是否轮到自己执行,当然此过程为了提高性能可能将线程先挂起,最终由前驱节点唤醒。

if(尝试获取锁失败) {

    创建node

    使用CAS方式把node插入到队列尾部

    while(true){

    if(尝试获取锁成功 并且 node的前驱节点为头节点){

把当前节点设置为头节点

    跳出循环

}else{

    使用CAS方式修改node前驱节点的waitStatus标识为signal

    if(修改成功)

        挂起当前线程 

}

}

为什么要使用闯入策略?可闯入的策略通常可以提供更高的总吞吐量。由于一般同步器颗粒度比较小,也可以说共享资源的范围较小,而线程从阻塞状态到被唤醒所消耗的时间周期可能是通过共享资源时间周期的几倍甚至几十倍,如此一来线程唤醒过程中将存在一个很大的时间周期空窗期,导致资源没有得到充分利用,为了提高吞吐量,引入这种闯入策略,它可以使在等待队列头结点从阻塞到被唤醒的时间段内闯入的线程直接获取锁并通过同步器,以便充分利用唤醒过程这一空窗期,大大增加了吞吐率。另外,闯入机制的实现对外提供一种竞争调节机制,即开发者可以在自定义同步器中定义闯入尝试获取的次数,假设次数为n则不断重复获取直到n次都获取不成功才把线程加入等待队列中,随着次数n的增加可以增大成功闯入的几率。同时,这种闯入策略可能导致等待队列中的线程饥饿,因为锁可能一直被闯入的线程获取,但由于一般持有同步器的时间很短暂而避免饥饿的发生,反之如果保护的代码体很长并且持有同步器的时间较长,这将大大增加等待队列无限等待的风险。

在实际情况中还是要根据用户需求制定策略,在一个公平性要求很高的场景,则可以把闯入策略去除掉以达到公平。在自定义同步器中可以通过AQS预留方法tryAcquire方法实现,只需判断当前线程是否为等待队列中头结点对应的线程,若不是则直接返回false,尝试获取失败。但前面这种公平性是相对Java语法语义层面上的公平性,在现实中JVM的实现会直接影响线程执行的顺序。

喜欢研究java的同学可以交个朋友,下面是本人的微信号:

Java并发框架——公平性的更多相关文章

  1. Java并发框架AbstractQueuedSynchronizer(AQS)

    1.前言 本文介绍一下Java并发框架AQS,这是大神Doug Lea在JDK5的时候设计的一个抽象类,主要用于并发方面,功能强大.在新增的并发包中,很多工具类都能看到这个的影子,比如:CountDo ...

  2. Java 并发系列之十:java 并发框架(2个)

    1. Fork/Join框架 2. Executor框架 3. ThreadPoolExecutor 4. ScheduledThreadPoolExecutor 5. FutureTask 6. t ...

  3. 深入理解Java并发框架AQS系列(一):线程

    深入理解Java并发框架AQS系列(一):线程 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念 一.概述 1.1.前言 重剑无锋,大巧不工 读j.u.c包下的源码,永远无法绕开的经典 ...

  4. 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念

    深入理解Java并发框架AQS系列(一):线程 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念 一.AQS框架简介 AQS诞生于Jdk1.5,在当时低效且功能单一的synchroni ...

  5. 深入理解Java并发框架AQS系列(四):共享锁(Shared Lock)

    深入理解Java并发框架AQS系列(一):线程 深入理解Java并发框架AQS系列(二):AQS框架简介及锁概念 深入理解Java并发框架AQS系列(三):独占锁(Exclusive Lock) 深入 ...

  6. 深入理解Java并发框架AQS系列(三):独占锁(Exclusive Lock)

    一.前言 优秀的源码就在那里 经过了前面两章的铺垫,终于要切入正题了,本章也是整个AQS的核心之一 从本章开始,我们要精读AQS源码,在欣赏它的同时也要学会质疑它.当然本文不会带着大家逐行过源码(会有 ...

  7. Java并发框架——AQS中断的支持

    线程的定义给我们提供了并发执行多个任务的方式,大多数情况下我们会让每个任务都自行执行结束,这样能保证事务的一致性,但是有时我们希望在任务执行中取消任务,使线程停止.在java中要让线程安全.快速.可靠 ...

  8. Java并发框架——什么是AQS框架

    什么是AQS框架 1995年sun公司发布了第一个java语言版本,可以说从jdk1.1到jdk1.4期间java的使用主要是在移动应用和中小型企业应用中,在此类领域中基本不用设计大型并发场景,当然也 ...

  9. Java并发框架——AQS之如何使用AQS构建同步器

    AQS的设计思想是通过继承的方式提供一个模板让大家可以很容易根据不同场景实现一个富有个性化的同步器.同步器的核心是要管理一个共享状态,通过对状态的控制即可以实现不同的锁机制.AQS的设计必须考虑把复杂 ...

随机推荐

  1. CAN通信要注意的问题

    CAN通信要注意的问题主要有: 1.参数配置 在初始化.启动.发送.接收 CAN信息时都要对CAN卡进行参数配置: (1)CAN卡的选择,我用到的是周立功的PCIE-9221,也就是DevType设备 ...

  2. 利用maven install jar到项目当中

    接着上面利用maven打好的jar包.把刚刚打好的包放入其他项目当中怎么办? 只需要在相同的目录下执行mvn install,maven会自动把jar放到本地仓库中. 这样,原先maven项目中缺少依 ...

  3. swift之属性

    知识点总结: 1.存储属性 struct Town{ let region = "South" //只读属性 var population = //读写属性 } 2.惰性存储属性 ...

  4. Spring使用webjar

    注意事项 这玩意很简单,但是我们第一次搞就是搞不成功,为什么呢?因为我们都用的是idea或者eclipse编译.webjar只能在maven上才能打包,所以在使用时,记得maven-clean和mav ...

  5. 编程英语之KNN算法

    School of Computer Science The University of Adelaide   Artificial Intelligence Assignment 2   Semes ...

  6. Laravel中构造方法中不能写return!!!

    今天遇到的大坑 在laravel中 __construct 这个方法中不能写return 完全不能返回 而且还会向下执行具体原因不知道为什么解决办法!!!!用中间件来实现就可以了 Over!!!

  7. Linux服务器搭建相关教程链接整理

    Linux: Linux 教程 | 菜鸟教程 linux下如何添加一个用户并且让用户获得root权限 - !canfly - 博客园 Git: 在 Linux 下搭建 Git 服务器 - 黄棣-dee ...

  8. Jmeter(七)_if控制器+循环控制器+计数器控制接口分支

    最近查阅了一下网上关于if控制器的文章,大同小异,几乎找不到原创,于是决定自己写一篇 下午测试接口,遇到了一个审核的流程.逻辑很简单,就是审核不通过之后返回去继续修改再提交,然后再审核,直到通过为止. ...

  9. gdb不知为何显示2次析构

    gdb不知为何显示2次析构 (金庆的专栏 2016.11) gdb 显示2次 A::~A(): (gdb) bt #0 A::~A (this=0x602010, __in_chrg=<opti ...

  10. chrome官方完整安装包

    But did you know Google allows you to download the full standalone installer of Chrome from its offi ...