CountDownLatch
俗称倒计时,技术锁,并不是为了加锁,而是通过计数达到等待的功能 等待的形式
让一组线程在全部启动完成之后,在一起执行(先启动的线程需要阻塞等待后启动的线程,直到一组线程全部都启动完成后,再一起执行) 主线程等待另外一组线程都执行完成之后,再继续执行。
一、重要方法
1. await
CountDownLatch
|-> await
AQS
|-> acquireSharedInterruptibly
CountDownLatch
|-> tryAcquire
称为等待,也可以称为加锁 代码
public void await ( ) throws InterruptedException {
sync. acquireSharedInterruptibly ( 1 ) ;
}
public boolean await ( long timeout, TimeUnit unit)
throws InterruptedException {
return sync. tryAcquireSharedNanos ( 1 , unit. toNanos ( timeout) ) ;
}
AQS的中断获取共享锁acquireSharedInterruptibly 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 ;
}
理解
await是等待,多个线程执行完成之后,才能继续,否则加入到同步队列中,所以tryAcquireShared,当state==0时,表示所有线程已经全部执行完成,再来就直接获取锁,而且是非公平的获取,有可能当前未加入同步队列的线程获取,也有可能是同步队列获取
2. countDown
CountDownLatch
|-> countDonw
AQS
|-> releaseShared
CountDownLatch
|-> tryReleaseShared
代码
源码
public final boolean releaseShared ( int arg) {
if ( tryReleaseShared ( arg) ) {
doReleaseShared ( ) ;
return true ;
}
return false ;
}
CountDownLatch的是否可以释放锁的方法 protected boolean tryReleaseShared ( int releases) {
for ( ; ; ) {
int c = getState ( ) ;
if ( c == 0 )
return false ;
int nextc = c- 1 ;
if ( compareAndSetState ( c, nextc) )
return nextc == 0 ;
}
}
理解
countDown方法,通过使用CAS方法来设置state的值,当值为0,表示所有的任务全部执行完成。
总结
倒计时充分利用了同步队列等待的原理,将主线程作为需要等待的同步节点,来获取共享锁,当state没有满足条件时,就会一直阻塞在同步队列中,使用countdown之后,如果state0,表示所有的任务执行完成,即让同步队列的第一个节点开始执行,即主线程。所以只有当state 0时,才表示执行完成,此处没有显示枷锁的操作,await方法就是将主线程加入到同步对列中,利用其阻塞的特性,达到倒计时的功能,其他线程相当于抢到锁的线程,其他线程执行完成之后,才会释放同步队列的第一个节点,让其执行,即主线程执行。