The methods java.lang.Object.notify()
and java.lang.Object.notifyAll()
are used to waken waiting thread(s). These methods must be called from code that holds the same object lock as the waiting thread(s).
Any thread that has called invokes wait()
expects to wake up and resume execution when some condition predicate becomes true. As recommended by CON18-J. Always invoke wait() and await() methods inside a loop, any waiting thread, when woken, will test its condition predicate, waiting threads should test their condition predicates upon receiving notifications and resume waiting if the predicate has not become true.they are false.
The methods notify()
and notifyAll()
of package java.lang.Object
are used to waken waiting thread(s). These methods must be invoked from code that holds the same object lock as the waiting thread(s)Consequently, the notifyAll()
method is recommended rather than the notify()
method. The notifyAll()
method will wake wakes up all threads , and only threads allows ones whose condition predicate is satisfied will remain awaketrue to resume execution. Furthermore, if all of the threads require a specific lock, only one will obtain the lock, and the others may, presumably, resume waiting. The notify()
method wakes up only one thread, and makes no guarantees as to which thread gets woken upis notified. If the thread's condition predicate is not satisifiedsatisfied, the chosen thread may resume waitingnot awaken, defeating the purpose of the notify()
call.
The notify()
method should may only be called invoked if:
- Every condition predicate on in every thread waiting on the object is satisfied when a notification is received by each, independently. In other words, any selected thread is allowed to wake up and resume.
- Only one thread must wake up on the notify signal. This is contingent on the condition predicate, in that, only one predicate must fulfill the condition and allow the thread to proceed. Multiple condition predicates in the same statement should be avoided.
- No untrusted code has access to the object being waited on. If untrusted code has access to this object, it can
wait()
on the object and intercept anotify()
call.
The java.util.concurrent
utilities (interface Condition
) provide the signal()
and signalAll()
methods to awaken waiting threads that are blocked on an await()
call. Like the notify()
method, the signal()
method wakes up any one of the threads that is waiting on the condition and consequently, may be insecure. It is always safer to use signalAll
albeit a small performance penalty. Similarly, any thread that is blocked on a wait()
method invocation on a Java object being used as a condition queue, should be notified using notifyAll()
.
...
This noncompliant code example demonstrates shows a complex multi-step process being undertaken by several threads. Each thread executes one step of the process; the step being currently performed is maintained enumerated by the step
field. Each thread waits for the step
field to indicate that it is time to perform that the corresponding thread's step. When it is time to perform its After performing the step, each thread does so. It then increments step
for to transfer control to the next thread, notifies the threadit, and exits.
Code Block | ||
---|---|---|
| ||
public class ProcessStep implements Runnable { private static final Object lock = new Object(); private static int time = 1; private int myStepstep; // doDo stuffoperations when the step rachesreaches this value public ProcessStep(int myStepstep) { this.myStepstep = myStepstep; } public void run() { try { synchronized (lock) { while (time != myStepstep) { lock.wait(); } // ... doDo stuffoperations time++; lock.notify(); } } catch (InterruptedException ie) { Thread.currentThread().interrupt(); // Reset interrupted status } } public static void main(String[] args) { for (int i = 5; i > 0; i--) { ProcessStep ms = new ProcessStep(i); new Thread(ms).start(); } } } |
This noncompliant code example violates the liveness property. Each thread has a different condition predicate, as each requires step
to have a different value before proceeding. The Object.notify()
method wakes up only one thread at a time; . unless it happens to wake up the thread that is to perform the next step, the program will deadlockdeadlocks.
Compliant Solution (notifyAll())
In this compliant solution, each thread uses all threads that have performed their own step use notifyAll()
to wake all of the notify other waiting threads when its step is complete. Consequently the proper thread can perform its next step, the respective threads that are ready can perform the task, while all other threads note that their whose condition predicate has not been satisified and is unsatisfied promptly go back to sleep.
Code Block | ||
---|---|---|
| ||
// ... public void run() { try { synchronized (lock) { while (time != myStepstep) { lock.wait(); } // ... do stuff time++; lock.notifyAll(); } } catch (InterruptedException ie) { Thread.currentThread().interrupt(); // Reset interrupted status } } |
...
Code Block | ||
---|---|---|
| ||
public class ProcessStep implements Runnable { private static final Lock lock = new ReentrantLock(); private static final Condition condition = lock.newCondition(); private static int time = 1; private int myStepstep; // doDo stuffoperations when the step rachesreaches this value public ProcessStep(int myStepstep) { this.myStepstep = myStepstep; } public void run() { lock.lock(); try { while (time != myStepstep) { condition.await(); } // ... doDo stuffoperations time++; condition.signal(); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); // Reset interrupted status } finally { lock.unlock(); } } public static void main(String[] args) { for (int i = 5; i > 0; i--) { ProcessStep ms = new ProcessStep(i); new Thread(ms).start(); } } } |
Similar to Object.notify()
, the condCondition.signal()
method may choose any one thread and awaken it.
...
Code Block | ||
---|---|---|
| ||
public void run() { lock.lock(); try { while (time != myStepstep) { condition.await(); } // ... do stuff time++; condition.signalAll(); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); // Reset interrupted status } finally { lock.unlock(); } } |
...
Code Block | ||
---|---|---|
| ||
public class ProcessStep implements Runnable { private static final Lock lock = new ReentrantLock(); private static final Condition[] conditions = new Condition[6]; private static int time = 1; private int myStepstep; // doDo stuffoperations when the step rachesreaches this value private static final Condition[] conditions = new Condition[step]; public ProcessStep(int myStepstep) { this.myStepstep = myStepstep; conditions[myStepstep] = lock.newCondition(); } public void run() { lock.lock(); try { while (time != myStepstep) { conditions[myStepstep].await(); } // ... doDo stuffoperations time++; if (myStepstep + 1 < conditions.length) { conditions[myStepstep + 1].signal(); } } catch (InterruptedException ie) { Thread.currentThread().interrupt(); // Reset interrupted status } finally { lock.unlock(); } } public static void main(String[] args) { for (int i = 5; i > 0; i--) { ProcessStep ms = new ProcessStep(i); new Thread(ms).start(); } } } |
...