码迷,mamicode.com
首页 > 其他好文 > 详细

由FutureTask的get方法靠什么机制来阻塞引发的思考

时间:2016-06-20 14:03:00      阅读:425      评论:0      收藏:0      [点我收藏+]

标签:

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

看都有谁实现了这个类:

技术分享

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

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

2. 分析AbstractQueuedSynchronizer

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

技术分享

中文的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锁简明介绍

a

由FutureTask的get方法靠什么机制来阻塞引发的思考

标签:

原文地址:http://www.cnblogs.com/simoncook/p/5600287.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!