zoukankan      html  css  js  c++  java
  • 由FutureTask的get方法靠什么机制来阻塞引发的思考

    1. FutureTask的get方法靠什么机制来阻塞

    看其get方法源码:

    /**
         * @throws CancellationException {@inheritDoc}
         */
        public V get() throws InterruptedException, ExecutionException {
            return sync.innerGet();
        }

    不难发现,FutureTask是依靠其内部类java.util.concurrent.FutureTask.Sync<V>类来实现阻塞。

    Sync又是实现了AbstractQueuedSynchronizer类。

    private final class Sync extends AbstractQueuedSynchronizer

    看都有谁实现了这个类:

    dza5vly3.q4n

    里面有很多我们平时用到的,但是不怎么清楚其原理的类,原来都是靠实现AbstractQueuedSynchronizer来达到相应的同步机制。

    AbstractQueuedSynchronizer又是靠什么来实现阻塞以及维持协调好各竞争线程间的资源分配的?看下一段。

    2. 分析AbstractQueuedSynchronizer

    从上面分析来看AbstractQueuedSynchronizer应该是JDK的concurrent包里比较重要的一个机制。用google先了解下他的面貌:

    image

    中文的blog的搜索结果说明有很多人对这个做了总结与学习,最下面框起来的一个pdf结果应该是对这个的一个论文。

    英文原文

    中文版

    论文中阐述了几点比较关键的地方

    1. 方法命名的问题

    同步器一般包含两种方法,一种是acquire,另一种是release。acquire操作阻塞调用的线程,直到或除非同步状态允许其继续执行。而release操作则是通过某种方式改变同步状态,使得一或多个被acquire阻塞的线程继续执行。

    j.u.c包中并没有对同步器的API做一个统一的定义。因此,有一些类定义了通用的接口(如Lock),而另外一些则定义了其专有的版本。因此在不同的 类中,acquire和release操作的名字和形式会各有不同。例 如:Lock.lock,Semaphore.acquire,CountDownLatch.await和FutureTask.get,在这个框架 里,这些方法都是acquire操作。但是,J.U.C为支持一系列常见的使用选项,在类间都有个一致约定。在有意义的情况下,每一个同步器都支持下面的 操作:

    阻塞和非阻塞(例如tryLock)同步。
    可选的超时设置,让调用者可以放弃等待
    通过中断实现的任务取消,通常是分为两个版本,一个acquire可取消,而另一个不可以。

    2. 实现同步器的三个“组件”

    为了实现上述操作,需要下面三个基本组件的相互协作:

    a)  同步状态的原子性管理;
    b) 线程的阻塞与解除阻塞;
    c) 队列的管理;

    怎么实现这三个部件,论文中有详细介绍。

    论文中提到“整个框架的关键就是如何管理被阻塞的线程的队列”也就是对应上面三个“组件”的c部分。

    AQS中使用了CLH队列。

    为什么采用CLH而不是MCS,因为CLH更容易实现取消与超时机制。

    3. CLH队列

    CLH锁简明介绍

    谈CLH队列时,前面要先谈很多基础知识,不然直接阅读上面的简明介绍,会有点坡度。

    4. AQS思维导图

    2016-11-30 09-24-56_XMind - D__600.self_05.code_04.java_21.JDK1.6_src_study_21.JDK1.6_src_study_docu

    2016-11-30 09-21-50_XMind - D__600.self_05.code_04.java_21.JDK1.6_src_study_21.JDK1.6_src_study_docu

    5. FutureTask思维导图

    2016-11-30 09-22-12_XMind - D__600.self_05.code_04.java_21.JDK1.6_src_study_21.JDK1.6_src_study_docu

  • 相关阅读:
    【rust】Rust 的构建系统和包管理工具Cargo认识并初步使用(2)
    【rust】rust安装,运行第一个Rust 程序 (1)
    linux 双网卡桥接,实现网卡流量镜像与转发
    【原创】使用golang访问windows telnet服务器
    使用centos 7安装conpot
    用Redis作Mysql数据库缓存
    python解析处理snmp回显----snmp
    snmp自定义OID与文件下载----服务器端配置
    golang map输出排序
    计算机组成原理---第1章 计算机系统概述
  • 原文地址:https://www.cnblogs.com/simoncook/p/5600287.html
Copyright © 2011-2022 走看看