Overview
Countdownlatch is a synchronization tool class that allows one or more threads to wait until the operation of another thread has finished executing.
Countdownlatch uses a counter count implementation that requires a given count initialization countdownlatch when building countdownlatch. Until count reaches 0, the thread that calls the await () method will block until count arrives at 0 o'clock, waking up all blocked threads. Note: The counter count cannot be reset, that is, this function can only be implemented once, which is also the difference between Countdownlatch and Cyclicbarrier.
Memory consistency effect: the operation before calling Countdown () in a thread happen-before immediately following the successful return of await () from another thread.
Use
Countdownlatch is a universal synchronization tool that has many uses. Countdownlatch, which counts 1 initialized, is used as a simple on/Guan, or Portal: All threads that call await are waiting at the entrance until a thread that calls Countdown () opens the portal. N-initialized Countdownlatch can cause a thread to wait until N threads complete an operation, or to wait until an operation completes N.
The method provided:
1 //blocks the current thread until the counter count becomes 0 unless interrupted2 Public voidAwait ()throwsinterruptedexception3 //blocks the current thread until the counter count becomes 0 unless it is interrupted or exceeds the specified time4 Public BooleanAwaitLongTimeout, timeunit unit)throwsinterruptedexception5 //decrements the counter count and wakes all waiting threads if count becomes 06 Public voidCountdown ()7 //returns the counter count value8 Public LongGetCount ()
Use example: The driver main thread controls the start of N worker threads and waits for all worker threads to complete before exiting.
1 classDriver {// ...2 voidMain ()throwsinterruptedexception {3Countdownlatch startsignal =NewCountdownlatch (1);//Start Signal4Countdownlatch donesignal =NewCountdownlatch (N);//Complete Signal5 6 for(inti = 0; i < N; ++i)//Create and start threads7 NewThread (NewWorker (startsignal, donesignal)). Start ();8 9Dosomethingelse ();//don ' t let run yetTen //set the start signal counter to 0 to start the waiting worker thread OneStartsignal.countdown ();//Let all threads proceed A Dosomethingelse (); - //wait for n worker threads to complete -Donesignal.await ();//wait for all to finish the } - } - - classWorkerImplementsRunnable { + Private FinalCountdownlatch startsignal; - Private FinalCountdownlatch donesignal; + Worker (Countdownlatch startsignal, Countdownlatch donesignal) { A This. startsignal =startsignal; at This. donesignal =donesignal; - } - Public voidrun () { - Try { -Startsignal.await ();//wait for the start signal - doWork (); inDonesignal.countdown ();//The completion signal is emitted, minus 1 of the counter that completes the signal -}Catch(Interruptedexception ex) {}//return; to } + - voiddoWork () {...} the}
Implementation principle
The Countdownlatch is based on the AQS implementation, using the synchronization state of Aqs to represent the counter count.
Let's take a look at the implementation of Countdownlatch's inner class Syns:
1 Private Static Final classSyncextendsAbstractqueuedsynchronizer {2 Private Static Final LongSerialversionuid = 4982264981922014374L;3 4Sync (intcount) {5SetState (count);//set synchronization state to count6 }7 8 intGetCount () {9 returnGetState ();//Query Synchronization StatusTen } One //overrides the Aqs shared way to get the synchronization state. Returns 1 when State=0, gets successful, returns 1 when State=1, gets failed. A protected intTryacquireshared (intacquires) { - return(getState () = = 0)? 1:-1; - } the //overrides the Aqs method of sharing the state of the release synchronization. Decreasing synchronization state based on spin CAS - protected BooleanTryreleaseshared (intreleases) { - //decrement count; signal when transition to zero - //if state=0, then return false directly + //if state>0, then the state is decremented. If the updated state=0 returns True, the synchronization state is released successfully, and the reverse returns false. - for (;;) { + intc =getState (); A if(c = = 0) at return false; - intNEXTC = c-1; - if(Compareandsetstate (c, NEXTC)) - returnNEXTC = = 0; - } - } in}
As can be seen from the sync source, Countdownlatch is based on the Aqs shared access and Release synchronization state mechanism implementation.
Await ()
1 // call Aqs to provide a shared-interrupt get synchronization state method. 2// If successful (state=0), continue execution of subsequent code; otherwise (state>0), block the current thread. 3publicvoidthrows interruptedexception {4 sync.acquiresharedinterruptibly (1); 5 }
Countdown ()
1 // invokes the shared-Release synchronization state method provided by Aqs. 2// If the release succeeds (tryreleaseshared returns True), wakes the successor on the synchronization queue, and does nothing if the release fails (tryreleaseshared returns false). 3publicvoid countdown () {4 sync.releaseshared (1); 5 }
Java Concurrency Programming--countdownlatch