我在网上找了一些关于CyclicBarrier的一些解释
In a nutshell, just to understand key functional differences between the two :
public class CountDownLatch {
private Object mutex = new Object();
private int count;
public CountDownLatch(int count) {
this.count = count;
}
public void await() throws InterruptedException {
synchronized (mutex) {
while (count > 0) {
mutex.wait();
}
}
}
public void countDown() {
synchronized (mutex) {
if (--count == 0)
mutex.notifyAll();
}
}
}
and
public class CyclicBarrier {
private Object mutex = new Object();
private int count;
public CyclicBarrier(int count) {
this.count = count;
}
public void await() throws InterruptedException {
synchronized (mutex) {
count--;
while(count > 0)
mutex.wait();
mutex.notifyAll();
}
}
}
except, of course, features like non-blocking, timed waiting, diagnostics and everything which has been in details explained in the above answers.
The above classes are, however, fully functional and equivalent, within the provided functionality, to their correspondent namesakes.
On a different note, CountDownLatch
's inner class subclasses AQS
, while CyclicBarrier
uses ReentrantLock
(my suspicion is it could be other way around or both could use AQS or both use Lock -- without any loss of performance efficiency)
还有notifyall()的解释
However (if I do understand the difference between these methods right), only one thread is always selected for further monitor acquisition.
That is not correct. o.notifyAll()
wakes all of the threads that are blocked in o.wait()
calls. The threads are only allowed to return from o.wait()
one-by-one, but they each will get their turn.
Simply put, it depends on why your threads are waiting to be notified. Do you want to tell one of the waiting threads that something happened, or do you want to tell all of them at the same time?
In some cases, all waiting threads can take useful action once the wait finishes. An example would be a set of threads waiting for a certain task to finish; once the task has finished, all waiting threads can continue with their business. In such a case you would use notifyAll() to wake up all waiting threads at the same time.
Another case, for example mutually exclusive locking, only one of the waiting threads can do something useful after being notified (in this case acquire the lock). In such a case, you would rather use notify(). Properly implemented, you could use notifyAll() in this situation as well, but you would unnecessarily wake threads that can't do anything anyway.
In many cases, the code to await a condition will be written as a loop:
synchronized(o) {
while (! IsConditionTrue()) {
o.wait();
}
DoSomethingThatOnlyMakesSenseWhenConditionIsTrue_and_MaybeMakeConditionFalseAgain();
}
That way, if an o.notifyAll()
call wakes more than one waiting thread, and the first one to return from the o.wait()
makes leaves the condition in the false state, then the other threads that were awakened will go back to waiting.
https://stackoverflow.com/questions/4168772/java-concurrency-countdown-latch-vs-cyclic-barrier
https://stackoverflow.com/questions/37026/java-notify-vs-notifyall-all-over-again