countDownLatch(CAS+UNSAFE.park)和cyclicBarrier(ReentrantLock)
countDownLatch
AQS(CAS-state)
初始化时,state被初始化
调用await,判断state的值,如果state=0,则不会阻塞线程;否则在哪个线程执行执行就会阻塞(UNSAFE.park)哪个线程。
然后countDown被调用,每调用一次,state会被减一,并判断此时state是否等于0,如果等于0则释放((UNSAFE.unpark))被阻塞线程
new countDownLatch的相关代码:新建AQS的子类Sync,初始化state的值
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
private static final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 4982264981922014374L;
Sync(int count) {
setState(count);
}
int getCount() {
return getState();
}
// state=0才获取到锁
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
// 减1后如果值为0表示获取了共享锁,释放锁
protected boolean tryReleaseShared(int releases) {
// Decrement count; signal when transition to zero
for (;;) {
int c = getState();
if (c == 0)
return false;
int nextc = c-1;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
}
await方法调用逻辑:
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
}
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
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;
}
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}
// 最终调用unsafe类阻塞线程
public static void park(Object blocker) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
UNSAFE.park(false, 0L);
setBlocker(t, null);
}
countdown方法调用:
public void countDown() {
sync.releaseShared(1);
}
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}
protected boolean tryReleaseShared(int releases) {
// Decrement count; signal when transition to zero
for (;;) {
int c = getState();
if (c == 0)
return false;
int nextc = c-1;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
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
unparkSuccessor(h);
}
else if (ws == 0 &&
!compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
continue; // loop on failed CAS
}
if (h == head) // loop if head changed
break;
}
}
//unparkSuccessor方法中最终释放锁:
LockSupport.unpark(s.thread);
cyclicBarrier
await为啥可以暂停自身(condition.await),await达到一定次数怎么放行的(condiition.signalAll)?
底层实现:ReentantLock + condition,每次调用await,先lock,后count--,判断count==0?singnal:con.await
CyclicBarrier的两个属性:
/** The lock for guarding barrier entry */
private final ReentrantLock lock = new ReentrantLock();
/** Condition to wait on until tripped */
private final Condition trip = lock.newCondition();
构造器:
public CyclicBarrier(int parties, Runnable barrierAction) {
if (parties <= 0) throw new IllegalArgumentException();
this.parties = parties;
this.count = parties;
this.barrierCommand = barrierAction;
}
await方法的调用:
public int await() throws InterruptedException, BrokenBarrierException {
try {
return dowait(false, 0L);
} catch (TimeoutException toe) {
throw new Error(toe); // cannot happen
}
}
private int dowait(boolean timed, long nanos)
throws InterruptedException, BrokenBarrierException,
TimeoutException {
final ReentrantLock lock = this.lock;
lock.lock();
try {
final Generation g = generation;
if (g.broken)
throw new BrokenBarrierException();
if (Thread.interrupted()) {
breakBarrier();
throw new InterruptedException();
}
int index = --count;
if (index == 0) { // tripped,await次数已够,放行
boolean ranAction = false;
try {
final Runnable command = barrierCommand;
if (command != null)
command.run();
ranAction = true;
// 这里面调用condition.signal 唤醒所有的线程
nextGeneration();
return 0;
} finally {
if (!ranAction)
breakBarrier();
}
}
// loop until tripped, broken, interrupted, or timed out
for (;;) {
try {
if (!timed)
// 线程阻塞
trip.await();
else if (nanos > 0L)
nanos = trip.awaitNanos(nanos);
} catch (InterruptedException ie) {
if (g == generation && ! g.broken) {
breakBarrier();
throw ie;
} else {
// We're about to finish waiting even if we had not
// been interrupted, so this interrupt is deemed to
// "belong" to subsequent execution.
Thread.currentThread().interrupt();
}
}
if (g.broken)
throw new BrokenBarrierException();
if (g != generation)
return index;
if (timed && nanos <= 0L) {
breakBarrier();
throw new TimeoutException();
}
}
} finally {
lock.unlock();
}
}
// 这里唤醒阻塞的线程
private void nextGeneration() {
// signal completion of last generation
trip.signalAll();
// set up next generation
count = parties;
generation = new Generation();
}
cyclic怎么理解,其中generation起到什么作用?
CyclicBarrier可以重复使用,条件是await达到次数或者调用reset方法均可,调用reset已经那些已经调用await的线程是怎么处理的?
会直接报BrokenBarrierException异常,程序不再执行。
reset时BrokenBarrierException异常怎么抛出来的?
public void reset() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
breakBarrier(); // break the current generation
nextGeneration(); // start a new generation
} finally {
lock.unlock();
}
}
很明显reset没有直接抛出异常,但是 breakBarrier了,即
private void breakBarrier() {
generation.broken = true;
count = parties;
trip.signalAll();
}
再仔细看下会发现doawait方法中,死循环中有这么一段代码:
if (g.broken)
throw new BrokenBarrierException();
这就对上了。。。。。。
CylicBarrier使用实例
public static void main(String[] args) throws InterruptedException, BrokenBarrierException {
CyclicBarrier cyclicBarrier = new CyclicBarrier(2, () -> System.out.println("aa"));
new Thread(new Innner(cyclicBarrier)).start();
// 确保reset后于上面的thread1执行
Thread.sleep(100);
cyclicBarrier.reset();
new Thread(new Innner(cyclicBarrier)).start();
cyclicBarrier.await();
}
static class Innner implements Runnable{
CyclicBarrier cyclicBarrier;
public Innner( CyclicBarrier cyclicBarrier){
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName()+" -start");
cyclicBarrier.await();
System.out.println(Thread.currentThread().getName()+" -end");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
countDownLatch和cyclicBarrier使用场景
countDownLatch(3): 商家(主线程)卖西瓜,规矩是必须三人(初始值为3)拼团才发货(调用await),第一个人下单(调用一次countDown),商家看了下没到三人,还差俩人(3-1=2),又有俩人下单,拼团成功,商家发货。
cyclicBarrier(3) :导游(即cyclicBarrier)带领仨人(三个任务线程)逛故宫,需要在故宫门口结合,现在每个人到了报告下(任务线程调用await来),第一个报告的需要等待另外两名游客,三游客都报告了;然后游客可以进门游览故宫,同时导游开始讲解(cyclicBarrier中的任务开始执行)。
countDownLatch和cyclicBarrier实现线程等待 https://blog.csdn.net/h2604396739/article/details/86615541