CountDownLatch.java revision f6c387128427e121477c1b32ad35cdcaa5101ba3
1/* 2 * Written by Doug Lea with assistance from members of JCP JSR-166 3 * Expert Group and released to the public domain, as explained at 4 * http://creativecommons.org/licenses/publicdomain 5 */ 6 7package java.util.concurrent; 8import java.util.concurrent.locks.*; 9import java.util.concurrent.atomic.*; 10 11/** 12 * A synchronization aid that allows one or more threads to wait until 13 * a set of operations being performed in other threads completes. 14 * 15 * <p>A <tt>CountDownLatch</tt> is initialized with a given 16 * <em>count</em>. The {@link #await await} methods block until the current 17 * {@link #getCount count} reaches zero due to invocations of the 18 * {@link #countDown} method, after which all waiting threads are 19 * released and any subsequent invocations of {@link #await await} return 20 * immediately. This is a one-shot phenomenon -- the count cannot be 21 * reset. If you need a version that resets the count, consider using 22 * a {@link CyclicBarrier}. 23 * 24 * <p>A <tt>CountDownLatch</tt> is a versatile synchronization tool 25 * and can be used for a number of purposes. A 26 * <tt>CountDownLatch</tt> initialized with a count of one serves as a 27 * simple on/off latch, or gate: all threads invoking {@link #await await} 28 * wait at the gate until it is opened by a thread invoking {@link 29 * #countDown}. A <tt>CountDownLatch</tt> initialized to <em>N</em> 30 * can be used to make one thread wait until <em>N</em> threads have 31 * completed some action, or some action has been completed N times. 32 * <p>A useful property of a <tt>CountDownLatch</tt> is that it 33 * doesn't require that threads calling <tt>countDown</tt> wait for 34 * the count to reach zero before proceeding, it simply prevents any 35 * thread from proceeding past an {@link #await await} until all 36 * threads could pass. 37 * 38 * <p><b>Sample usage:</b> Here is a pair of classes in which a group 39 * of worker threads use two countdown latches: 40 * <ul> 41 * <li>The first is a start signal that prevents any worker from proceeding 42 * until the driver is ready for them to proceed; 43 * <li>The second is a completion signal that allows the driver to wait 44 * until all workers have completed. 45 * </ul> 46 * 47 * <pre> 48 * class Driver { // ... 49 * void main() throws InterruptedException { 50 * CountDownLatch startSignal = new CountDownLatch(1); 51 * CountDownLatch doneSignal = new CountDownLatch(N); 52 * 53 * for (int i = 0; i < N; ++i) // create and start threads 54 * new Thread(new Worker(startSignal, doneSignal)).start(); 55 * 56 * doSomethingElse(); // don't let run yet 57 * startSignal.countDown(); // let all threads proceed 58 * doSomethingElse(); 59 * doneSignal.await(); // wait for all to finish 60 * } 61 * } 62 * 63 * class Worker implements Runnable { 64 * private final CountDownLatch startSignal; 65 * private final CountDownLatch doneSignal; 66 * Worker(CountDownLatch startSignal, CountDownLatch doneSignal) { 67 * this.startSignal = startSignal; 68 * this.doneSignal = doneSignal; 69 * } 70 * public void run() { 71 * try { 72 * startSignal.await(); 73 * doWork(); 74 * doneSignal.countDown(); 75 * } catch (InterruptedException ex) {} // return; 76 * } 77 * 78 * void doWork() { ... } 79 * } 80 * 81 * </pre> 82 * 83 * <p>Another typical usage would be to divide a problem into N parts, 84 * describe each part with a Runnable that executes that portion and 85 * counts down on the latch, and queue all the Runnables to an 86 * Executor. When all sub-parts are complete, the coordinating thread 87 * will be able to pass through await. (When threads must repeatedly 88 * count down in this way, instead use a {@link CyclicBarrier}.) 89 * 90 * <pre> 91 * class Driver2 { // ... 92 * void main() throws InterruptedException { 93 * CountDownLatch doneSignal = new CountDownLatch(N); 94 * Executor e = ... 95 * 96 * for (int i = 0; i < N; ++i) // create and start threads 97 * e.execute(new WorkerRunnable(doneSignal, i)); 98 * 99 * doneSignal.await(); // wait for all to finish 100 * } 101 * } 102 * 103 * class WorkerRunnable implements Runnable { 104 * private final CountDownLatch doneSignal; 105 * private final int i; 106 * WorkerRunnable(CountDownLatch doneSignal, int i) { 107 * this.doneSignal = doneSignal; 108 * this.i = i; 109 * } 110 * public void run() { 111 * try { 112 * doWork(i); 113 * doneSignal.countDown(); 114 * } catch (InterruptedException ex) {} // return; 115 * } 116 * 117 * void doWork() { ... } 118 * } 119 * 120 * </pre> 121 * 122 * @since 1.5 123 * @author Doug Lea 124 */ 125public class CountDownLatch { 126 /** 127 * Synchronization control For CountDownLatch. 128 * Uses AQS state to represent count. 129 */ 130 private static final class Sync extends AbstractQueuedSynchronizer { 131 Sync(int count) { 132 setState(count); 133 } 134 135 int getCount() { 136 return getState(); 137 } 138 139 public int tryAcquireShared(int acquires) { 140 return getState() == 0? 1 : -1; 141 } 142 143 public boolean tryReleaseShared(int releases) { 144 // Decrement count; signal when transition to zero 145 for (;;) { 146 int c = getState(); 147 if (c == 0) 148 return false; 149 int nextc = c-1; 150 if (compareAndSetState(c, nextc)) 151 return nextc == 0; 152 } 153 } 154 } 155 156 private final Sync sync; 157 /** 158 * Constructs a <tt>CountDownLatch</tt> initialized with the given 159 * count. 160 * 161 * @param count the number of times {@link #countDown} must be invoked 162 * before threads can pass through {@link #await}. 163 * 164 * @throws IllegalArgumentException if <tt>count</tt> is less than zero. 165 */ 166 public CountDownLatch(int count) { 167 if (count < 0) throw new IllegalArgumentException("count < 0"); 168 this.sync = new Sync(count); 169 } 170 171 /** 172 * Causes the current thread to wait until the latch has counted down to 173 * zero, unless the thread is {@link Thread#interrupt interrupted}. 174 * 175 * <p>If the current {@link #getCount count} is zero then this method 176 * returns immediately. 177 * <p>If the current {@link #getCount count} is greater than zero then 178 * the current thread becomes disabled for thread scheduling 179 * purposes and lies dormant until one of two things happen: 180 * <ul> 181 * <li>The count reaches zero due to invocations of the 182 * {@link #countDown} method; or 183 * <li>Some other thread {@link Thread#interrupt interrupts} the current 184 * thread. 185 * </ul> 186 * <p>If the current thread: 187 * <ul> 188 * <li>has its interrupted status set on entry to this method; or 189 * <li>is {@link Thread#interrupt interrupted} while waiting, 190 * </ul> 191 * then {@link InterruptedException} is thrown and the current thread's 192 * interrupted status is cleared. 193 * 194 * @throws InterruptedException if the current thread is interrupted 195 * while waiting. 196 */ 197 public void await() throws InterruptedException { 198 sync.acquireSharedInterruptibly(1); 199 } 200 201 /** 202 * Causes the current thread to wait until the latch has counted down to 203 * zero, unless the thread is {@link Thread#interrupt interrupted}, 204 * or the specified waiting time elapses. 205 * 206 * <p>If the current {@link #getCount count} is zero then this method 207 * returns immediately with the value <tt>true</tt>. 208 * 209 * <p>If the current {@link #getCount count} is greater than zero then 210 * the current thread becomes disabled for thread scheduling 211 * purposes and lies dormant until one of three things happen: 212 * <ul> 213 * <li>The count reaches zero due to invocations of the 214 * {@link #countDown} method; or 215 * <li>Some other thread {@link Thread#interrupt interrupts} the current 216 * thread; or 217 * <li>The specified waiting time elapses. 218 * </ul> 219 * <p>If the count reaches zero then the method returns with the 220 * value <tt>true</tt>. 221 * <p>If the current thread: 222 * <ul> 223 * <li>has its interrupted status set on entry to this method; or 224 * <li>is {@link Thread#interrupt interrupted} while waiting, 225 * </ul> 226 * then {@link InterruptedException} is thrown and the current thread's 227 * interrupted status is cleared. 228 * 229 * <p>If the specified waiting time elapses then the value <tt>false</tt> 230 * is returned. 231 * If the time is 232 * less than or equal to zero, the method will not wait at all. 233 * 234 * @param timeout the maximum time to wait 235 * @param unit the time unit of the <tt>timeout</tt> argument. 236 * @return <tt>true</tt> if the count reached zero and <tt>false</tt> 237 * if the waiting time elapsed before the count reached zero. 238 * 239 * @throws InterruptedException if the current thread is interrupted 240 * while waiting. 241 */ 242 public boolean await(long timeout, TimeUnit unit) 243 throws InterruptedException { 244 return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout)); 245 } 246 247 /** 248 * Decrements the count of the latch, releasing all waiting threads if 249 * the count reaches zero. 250 * <p>If the current {@link #getCount count} is greater than zero then 251 * it is decremented. If the new count is zero then all waiting threads 252 * are re-enabled for thread scheduling purposes. 253 * <p>If the current {@link #getCount count} equals zero then nothing 254 * happens. 255 */ 256 public void countDown() { 257 sync.releaseShared(1); 258 } 259 260 /** 261 * Returns the current count. 262 * <p>This method is typically used for debugging and testing purposes. 263 * @return the current count. 264 */ 265 public long getCount() { 266 return sync.getCount(); 267 } 268 269 /** 270 * Returns a string identifying this latch, as well as its state. 271 * The state, in brackets, includes the String 272 * "Count =" followed by the current count. 273 * @return a string identifying this latch, as well as its 274 * state 275 */ 276 public String toString() { 277 return super.toString() + "[Count = " + sync.getCount() + "]"; 278 } 279 280} 281