jdk 源码分析(15)java CountDownLatch 源码解析
2017-08-05 10:51
495 查看
CountDownLatch 和CyclicBarrier 和 Semaphore 在使用的时候有类似,底层实现也很相似的。将分布介绍一下,
CountDownLatch 和lock的机制很相似,(参考lock:jdk
源码分析(7)java ReentrantLock结构)
相同点:
1)lock需要队列保存竞争的线程,CountDownLatch需要队列(链表)保持等待的线程线程,
2)都需要park和unpark。
不同点:
1)lock (重入锁)是争论的谁能将state 变成1,而CountDownLatch 是大家一起齐心协力将state 变成0,
2)lock 是改变不了state的线程park,而CountDownLatch 是需要等待的线程park,
3)lock的upark 是另一个线程不再使用state时,选择队列的第一个线程park,而CountDownLatch是其他线程一起将state
从一个非零值变成零后 park.
1)CountDownLatch 最后是改变的AbstractQueuedSynchronizer的state 和lock 一样
1)CountDownLatch
await()方法主要调用这个方法,一般await用来暂停需要等待的线程(比如主线程)
countDown 方法:
细看上面里面的实现:
tryReleaseShared : 每次会减少1,一直到==0 否则都是范围false,false 就不会执行doReleaseShared();
最后看看doReleaseShared()
CountDownLatch 解析过程结束:
CountDownLatch 和lock的机制很相似,(参考lock:jdk
源码分析(7)java ReentrantLock结构)
相同点:
1)lock需要队列保存竞争的线程,CountDownLatch需要队列(链表)保持等待的线程线程,
2)都需要park和unpark。
不同点:
1)lock (重入锁)是争论的谁能将state 变成1,而CountDownLatch 是大家一起齐心协力将state 变成0,
2)lock 是改变不了state的线程park,而CountDownLatch 是需要等待的线程park,
3)lock的upark 是另一个线程不再使用state时,选择队列的第一个线程park,而CountDownLatch是其他线程一起将state
从一个非零值变成零后 park.
1)CountDownLatch 最后是改变的AbstractQueuedSynchronizer的state 和lock 一样
public CountDownLatch(int count) { if (count < 0) throw new IllegalArgumentException("count < 0"); this.sync = new Sync(count); }
1)CountDownLatch
await()方法主要调用这个方法,一般await用来暂停需要等待的线程(比如主线程)
private void doAcquireSharedInterruptibly(int arg)
throws InterruptedException {
//首先会添加到链表中,这里会记录当前线程,方法取消等待时能找到位置。
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head) {
int r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null; // help GC
failed = false;
return;
}
}
//让当前线程进入等待,使用supportLock.park 方法
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
countDown 方法:
public final boolean releaseShared(int arg) {
//这里主要是判断是否已经达release 要求,
if (tryReleaseShared(arg)) {
//释放park
doReleaseShared();
return true;
}
return false;
}
细看上面里面的实现:
tryReleaseShared : 每次会减少1,一直到==0 否则都是范围false,false 就不会执行doReleaseShared();
protected boolean tryReleaseShared(int releases) {
// Decrement count; signal when transition to zero
//这里采用了循环,这是乐观锁的一种实现,一直尝试,直到成功,
for (;;) {
int c = getState();
if (c == 0)
return false;
// 每次会减少1
int nextc = c-1;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
最后看看doReleaseShared()
private void doReleaseShared() {
for (;;) {
Node h = head;
if (h != null && h != tail) {
int ws = h.waitStatus;
if (ws == Node.SIGNAL) {
if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
continue;// loop to recheck cases
//h 里面保存了await暂停的线程,直接释放就可以了,完成了等待过程。
unparkSuccessor(h);
}
else if (ws == 0 &&
!compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
continue;// loop on failed CAS
}
if (h == head) // loop if head changed
break;
}
}
CountDownLatch 解析过程结束:
相关文章推荐
- jdk 源码分析(17)java Semaphore 源码解析及与lock对比
- Java并发Concurrent包的锁(六)——CountDownLatch源码分析及使用
- Java并发系列之CountDownLatch源码分析
- 【JUC】JDK1.8源码分析之CountDownLatch(五)
- java.util.concurrent.CountDownLatch控制线程执行工具类源码解析
- Java并发之CountDownLatch的使用和源码解析
- jdk 源码分析(16)java CyclicBarrier 源码解析
- JDK源码分析:java.lang.Boolean
- Java Collections Framework之LinkedList源码分析(基于JDK1.6)
- 【jdk源码解析二】java.uti.HashMap源码解析
- Java Collections Framework之Deque(LinkedList实现)源码分析(基于JDK1.6)(已补充)
- Java concurrent Framework并发容器之ConcurrentHashMap(Doug Lea 非JDK版)源码分析
- Java Collections Framework之HashMap源码分析(基于JDK1.6)
- java ArrayList 源码解析(jdk1.6)
- Java Collections Framework之LinkedHashMap源码分析(基于JDK1.6)(??)
- Java Collections Framework之HashSet及LinkedHashSet源码分析(基于JDK1.6)
- [置顶] JDK-CountDownLatch-实例、源码和模拟实现
- Java Collections Framework之ArrayList源码分析(基于JDK1.6)
- java动态代理Proxy源码解析(Jdk 1.6)
- Java Collections Framework之Stack源码分析缺陷,栈改进版(通过LinkedList实现)(基于JDK1.6)