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