- 浏览: 170020 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
zxjlwt:
学习了。http://surenpi.com
ANTLR 学习 -
qizhongfei:
JBPM 和 drools 怎么结合使用的?
Drools and Jbpm 学习 -
qizhongfei:
哥们,有些问题需要咨询,请加QQ:894596225 谢谢了。 ...
Drools and Jbpm 学习 -
weir2009:
红旗可以么
在 Linux 平台下安装 DB2 Express C -
bruce008:
其实这个optional 为true 的时候还有个很管用的用法 ...
Maven 在项目中的依赖管理
看完书 java concurrency in practice 当然是想找点啥好玩的东东玩玩。 当看到了Doug Lee 的论文 << The java.util.concurrent Synchronizer Framework >> 大呼来的太晚喔, 前段时间看那个ReentrantLock 的代码真的是痛苦啊,不过现在也不晚不是。 呵呵, 上菜:这个框架的核心是一个AbstractQueuedSynchronizer 类 (下面简称AQS) 它基本上的思路是:
- 采用Template Method Pattern. 它实现了non-contended 的synchronization 算法;
- 继承 它的Subclass 一般不直接作为Synchronzier, 而是作为私有的实现 被用来delegate. 比如 他举了个例子:
class Mutex implements Lock, java.io.Serializable {
// Our internal helper class private static class Sync extends AbstractQueuedSynchronizer { ..... } // The sync object does all the hard work. We just forward to it. private final Sync sync = new Sync(); public void lock() { sync.acquire(1); } public boolean tryLock() { return sync.tryAcquire(1); } public void unlock() { sync.release(1); } public Condition newCondition() { return sync.newCondition(); } public boolean isLocked() { return sync.isHeldExclusively(); } public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); } public void lockInterruptibly() throws InterruptedException { sync.acquireInterruptibly(1); } public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireNanos(1, unit.toNanos(timeout)); } }
在这个 AQS 类中 提供了 两大类方法
acquire 其中还包括 非阻塞的 tryAcquire; 带 time out 的;可以通过interruption 来cancellality 的。
release 相对简单点, 因为在调用release 方法的时候基本上暗含了个意思当前的线程是获得了锁的。
在JUC 包中没有为各种Synchronizer 类提供统一的API 比如 Lock.lock, Semaphore.acquire, CountDownLatch.await and FutureTask.get 都是映射到这个AQS 的 acquire 方法。
要实现一个Synchronizer 的基本思路非常直接的
acquire 操作
采用CAS 操作去更新同步状态 如果不成功 {
enqueue 当前线程
block 当前线程
}
dequeue 当前线程 if it was queued // 此时应该是当前线程被别的线程 release 来唤醒的。
release 操作 :
更新同步状态, 此时可以直接 set 而不通过 CAS。
假如 等待队列中还有线程 unblock one or more
要支持这些操作 需要 三类基本的组件:
1, Atomically managing synchronization state。 这个通过
private volatile int state;
在处理acquire 的时候基本是通过用CAS 实现的 compareAndSetState 来
2, Block /Unblock 线程 。 这个是通过 JUC 里面的一个封装类 LockSupport.park / unpark 来实现的。LockSupport 都deleget 到了 Unsafte 对应的方法
3, 维护 一个队列来存放 等待线程。 这个是通过一个 CLH queue 的变种。 它是一种linked queue 的通过 head 和tail 。
三个里面最复杂的就是这个 CLH queue 的维护了, queue 中节点被定义为 :
static final class Node {
volatile int waitStatus; volatile Node prev; volatile Node next; volatile Thread thread; Node nextWaiter; final boolean isShared() { return nextWaiter == SHARED; } final Node predecessor() throws NullPointerException { Node p = prev; if (p == null) throw new NullPointerException(); else return p; } Node() { // Used to establish initial head or SHARED marker } Node(Thread thread, Node mode) { // Used by addWaiter this.nextWaiter = mode; this.thread = thread; } Node(Thread thread, int waitStatus) { // Used by Condition this.waitStatus = waitStatus; this.thread = thread; } }
AQS 中定义了
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
这个方法通常在 acquire 的时候如果 tryAcquire 失败就会将insert 一个 Node 到 tail 之后, 并且 node.prev 指向先前的 tail。 当然这个是在 compareAndSetTail(pred, node) 返回true 的时候比较简单, 否则就进入 enq(node) 方法 差不多也是这个逻辑 insert 一个 Node 到 tail 之后。
在 1.6.0_25 版本里面AQS 就没有在 release 的时候 通过唤醒等待队列里面head指向的线程, 然后然后该线程是在 方法里面继续resume, 基本上会
基本上来讲 有了 这个 AQS , 我们要想实现一个 Synchronizer 就比较简单了, 最简单的情况下 treAcquire , tryRelease 实现下。AQS 里面提供的需要继承的方法不是采用abstract 的方式 而是用抛出 notImplementedException的 方式, 如果像那些tryAcquireShared 之类的 在 exclusive 模式下根本就不会被调用到, 我们也就根本就不必override。 比如 先前我们所的那个 Mutex 我们只需要定义它的内部类 Sync
// Our internal helper class private static class Sync extends AbstractQueuedSynchronizer { // Report whether in locked state protected boolean isHeldExclusively() { return getState() == 1; } // Acquire the lock if state is zero public boolean tryAcquire(int acquires) { assert acquires == 1; // Otherwise unused if (compareAndSetState(0, 1)) { setExclusiveOwnerThread(Thread.currentThread()); return true; } return false; } // Release the lock by setting state to zero protected boolean tryRelease(int releases) { assert releases == 1; // Otherwise unused if (getState() == 0) throw new IllegalMonitorStateException(); setExclusiveOwnerThread(null); setState(0); return true; } // Provide a Condition Condition newCondition() { return new ConditionObject(); } }
这个框架是非常精巧的, 还有很多地方比如那个 ConditionObject 里面涉及到另外一个单独的condition queue。只有再慢慢的啃了。
另外贴一张本人手工画的图,非常潦草多包涵了。
发表评论
-
How to implement a system with high throughput , low latency
2016-06-08 15:53 610Do not use locks in the main t ... -
给Spring 4.1.X 的Gradle 配置代理
2015-09-09 11:20 694Spring 现在不再使用Maven build 代码 改 ... -
SSL cert
2013-03-01 05:53 1344we use lots of ssh to access t ... -
使用StAX pull parser 解析XML 文档
2012-11-06 17:32 1542平时我们用解析Xml 文档 ... -
自定义ant task 验证POM文件版本依赖
2012-05-07 16:08 1736经常在项目里要涉及到N个Maven 项目之间有依赖, 常见的是 ... -
Jenkins 下的Glassfish 部署不能 重新部署的解决
2012-04-28 10:59 2392用Jenkins 作为 CI 用起来是非常的方便 但是 在用到 ... -
Hibernate 对事务的支持
2012-04-03 09:48 1077我们这里只讨论Hibernate 对事务的支持,注意没有涉及到 ... -
深入浅出 JTA 分布式事务
2012-04-02 12:44 01, JTA 2, XA 一 ... -
Java 内存模型以及并发编程点滴
2012-03-17 22:37 1192感觉java 的并发编程没有那么神秘的也就是基于JSR 133 ... -
ReentrantLock Fair 与 Unfair 的巨大差异
2012-03-05 09:41 2630ReentrantLock 可重入的锁是我们平常除了intr ... -
在EJB 中 配置Hibernate支持JTA
2012-03-01 15:38 2345Finally, 搞清楚了些Hibernate 的对JTA ... -
Disruptor 模式一个高性能的线程间消息机制
2012-02-08 11:24 195112306 的伤不起 引起了网上很多大牛的讨论 要是我们自己来 ... -
EJB 中 事务的粒度问题
2012-01-10 23:02 1068今天碰到一个 Hibernate flush 里 一些本不想 ... -
在tomcat 中调用远程EJB
2011-10-21 17:52 735目前做跟JavaEE, Spring ,JSF a ... -
Maven plugin in Eclipse
2011-10-21 13:27 1060今天帮一个同事fix一个失败的 unit test时候, 发 ... -
Case: 怎样捕捉针对domain 对象的批量修改的请求
2011-09-28 22:51 980从题目上看到这是一个很奇怪的需要。 具体说来现在有 ... -
EclipseLink 对JPA Query 实现的优化实现
2011-09-23 23:16 5343今天同事碰到一个JPA Query 的问题, 在业务上我们有4 ... -
online to publish my article for memory
2011-09-20 13:39 1063在JavaEye注册了这个账号很长时间了, 但是到目前都没有 ...
相关推荐
1. java.util.concurrent - Java 并发工具包 2. 阻塞队列 BlockingQueue 3. 数组阻塞队列 ArrayBlockingQueue 4. 延迟队列 DelayQueue 5. 链阻塞队列 LinkedBlockingQueue 6. 具有优先级的阻塞队列 ...
Tomcat内存溢出的解决方法(java.util.concurrent.ExecutionException:java.lang.OutOfMemoryError),内附解决方案!
java.util.concurrent系列文章(1) java.util.concurrent系列文章(1) java.util.concurrent系列文章(1) java.util.concurrent系列文章(1)
java并发工具包 java.util.concurrent中文版-带书签版
concurrent Synchronizer Framework,讲解整个并发框架的设计思路!
java.util.concurrent总体概览图。 收取资源分3分。需要的同学可以下载一下。 java.util.concurrent主要包括5个部分executor,colletions,locks,atomic,tools。 该图详细的列举了并发包下面的结构,包含所有接口和...
java并发工具包 java.util.concurrent中文版pdf
java.util.concurrent - Java 并发工具包 2. 阻塞队列 BlockingQueue 3. 数组阻塞队列 ArrayBlockingQueue 4. 延迟队列 DelayQueue 5. 链阻塞队列 LinkedBlockingQueue 6. 具有优先级的阻塞队列 ...
本文通过对数据压缩算法的简要介绍,然后以详细的示例演示了利用java.util.zip包实现数据的压缩与解压,并扩展到在网络传输方面如何应用java.util.zip包现数据压缩与解压
AQS作者Doug lea关于AQS设计、性能的paper,需要了解AQS的设计思想,思路可以参考这篇paper
如何启动:以win7系统为例,最好jdk8 1.打开cmd,cd到jdk的path,本机是:cd C:\Java\jdk6\bin ...java -cp D:\javaConcurrentAnimated.jar vgrazi.concurrent.samples.launcher.ConcurrentExampleLauncher
The java.util.concurrent synchronizer framework from Doug Lea
Java并发编程工具包java.util.concurrent的UML类结构图 PDF
JDK1.5中的线程池(java.util.concurrent.ThreadPoolExecutor)使用
主要介绍了java.util.concurrent.ExecutionException 问题解决方法的相关资料,需要的朋友可以参考下
java.util.concurrent系列文章(2) java.util.concurrent系列文章(2) java.util.concurrent系列文章(2) java.util.concurrent系列文章(2)
java.util.ConcurrentModificationException 异常问题详解1
详细介绍了java.util.logging.Logger的用法和结构,对如果扩展Logger起到抛砖引玉的作用!尊重劳动成果,亲下载了要给个评价!