java.util.concurrent包图文源码解析(一)——CountDownLatch
2017-07-15 17:41
681 查看
好久没有写博客了,四个字:贵在坚持!!!
从JAVA并发开始,所有的博文都结合源码,什么事情知道原理,得心应手。
java.util.concurrent包是线程控制框架,所谓的框架,就是提供有限的接口去实现极可能多的控制,大了说Spring,小了说线程池。
废话不多说,先来张图:
加入CLH队列的代码如下:
上面代码的思想:构造双向链表,其中head节点是一个没有没有thread的节点。其中属性
waitStatus
值为1,表示当前的线程被取消;
值为-1,表示当前节点的后继节点包含的线程需要运行,也就是unpark;
值为-2,表示当前节点在等待condition,也就是在condition队列中;
值为-3,表示当前场景下后续的acquireShared能够得以执行;
值为0,表示当前节点在sync队列中,等待着获取锁。
thread 封装的线程
调用AbstractQueuedSynchronizer的doReleaseShared()方法
这段代码逻辑总结:
如果当前head节点waitStatus==Node.SIGNAL,那么设置waitStatus=0,设置成功唤醒head的后继阻塞node,执行 unparkSuccessor(h);结合阻塞的代码doAcquireSharedInterruptibly,知道如果线程解锁之后会执行
会将head之后的第一个节点设置为head,并设置PROPAGATE,代码如下
会再次执行doReleaseShared()方法唤醒下一个节点。doReleaseShared()的跳出条件就是
如果当前head节点waitStatus==0,那么设置waitStatus=Node.PROPAGATE
从JAVA并发开始,所有的博文都结合源码,什么事情知道原理,得心应手。
java.util.concurrent包是线程控制框架,所谓的框架,就是提供有限的接口去实现极可能多的控制,大了说Spring,小了说线程池。
废话不多说,先来张图:
代码剖析 CountDownLatch
CountDownLatch的使用如下://同一个latch也可以被很多 线程持有,那么唤醒的时候需要依次唤醒 CountDownLatch latch=new CountDownLatch(2); latch.await(); doSomething(); latch.countDown(); doSomethind();
latch.await() 加入阻塞队列
public void await() throws InterruptedException { sync.acquireSharedInterruptibly(1); } //执行的是AbstractQueuedSynchronizer的acquireSharedInterruptibly() public final void acquireSharedInterruptibly(int arg) throws InterruptedException { if (Thread.interrupted())//如果当前线程被interrupt,那么抛出异常,相当于阻塞的退出 throw new InterruptedException(); if (tryAcquireShared(arg) < 0)//在各个子类Sync中实现 doAcquireSharedInterruptibly(arg); } //tryAcquireShared在CountDownLatch的内部类Sync中实现: /** * 阻塞的条件,如果当前的state>0那么就一直阻塞。 * 阻塞的代码在AQS的doAcquireSharedInterruptibly */ protected int tryAcquireShared(int acquires) { return (getState() == 0) ? 1 : -1; } //下面是阻塞代码doAcquireSharedInterruptibly
加入CLH队列的代码如下:
上面代码的思想:构造双向链表,其中head节点是一个没有没有thread的节点。其中属性
waitStatus
值为1,表示当前的线程被取消;
值为-1,表示当前节点的后继节点包含的线程需要运行,也就是unpark;
值为-2,表示当前节点在等待condition,也就是在condition队列中;
值为-3,表示当前场景下后续的acquireShared能够得以执行;
值为0,表示当前节点在sync队列中,等待着获取锁。
thread 封装的线程
countDown 释放锁
public void countDown() { sync.releaseShared(1);//共享 } 会调用AbstractQueuedSynchronizer的releaseShared方法:
调用AbstractQueuedSynchronizer的doReleaseShared()方法
这段代码逻辑总结:
如果当前head节点waitStatus==Node.SIGNAL,那么设置waitStatus=0,设置成功唤醒head的后继阻塞node,执行 unparkSuccessor(h);结合阻塞的代码doAcquireSharedInterruptibly,知道如果线程解锁之后会执行
会将head之后的第一个节点设置为head,并设置PROPAGATE,代码如下
会再次执行doReleaseShared()方法唤醒下一个节点。doReleaseShared()的跳出条件就是
如果当前head节点waitStatus==0,那么设置waitStatus=Node.PROPAGATE
CountDownLatch列子
相关文章推荐
- java.util.concurrent包图文源码解析(二)——ReentrantLock
- java.util.concurrent.ConcurrentHashMap并发哈希表源码解析
- java.util.concurrent.CountDownLatch控制线程执行工具类源码解析
- java.util.concurrent.CyclicBarrier同步屏障工具类源码解析
- 聊聊高并发(四十)解析java.util.concurrent各个组件(十六) ThreadPoolExecutor源码分析
- java.util.concurrent.locks.ReentrantReadWriteLock读写锁源码解析
- Java 并发工具包-java.util.concurrent-源码jdk1.7全面解析
- java.util.concurrent解析——ThreadPoolExecutor源码解析
- java.util.concurrent.locks.AbstractQueuedSynchronizer队列同步器源码解析
- java.util.concurrent.locks.ReentrantLock重入锁源码解析
- 《java.util.concurrent 包源码阅读》21 CyclicBarrier和CountDownLatch
- 聊聊高并发(二十三)解析java.util.concurrent各个组件(五) 深入理解AQS(三)
- java.util.concurrent.DelayQueue 源码学习
- 聊聊高并发(十二)分析java.util.concurrent.atomic.AtomicStampedReference源码来看如何解决CAS的ABA问题
- java.util.concurrent 用法实例详解 -中的java源码
- java.util.Hashtable源码解析
- 6种基础排序算法java源码+图文解析
- 《java.util.concurrent 包源码阅读》13 线程池系列之ThreadPoolExecutor 第三部分
- 聊聊高并发(三十九)解析java.util.concurrent各个组件(十五) 理解ExecutorService接口的设计
- 《java.util.concurrent 包源码阅读》 结束语