Deadlock example in Multi threading - java

While going through examples on Deadlock, I came across this code:
public class TestDeadlockExample1 {
public static void main(String[] args) {
final String resource1 = "ratan jaiswal";
final String resource2 = "vimal jaiswal";
// t1 tries to lock resource1 then resource2
Thread t1 = new Thread() {
public void run() {
synchronized (resource1) {
System.out.println("Thread 1: locked resource 1");
try { Thread.sleep(100);} catch (Exception e) {}
synchronized (resource2) {
System.out.println("Thread 1: locked resource 2");
}
}
}
};
// t2 tries to lock resource2 then resource1
Thread t2 = new Thread() {
public void run() {
synchronized (resource2) {
System.out.println("Thread 2: locked resource 2");
try { Thread.sleep(100);} catch (Exception e) {}
synchronized (resource1) {
System.out.println("Thread 2: locked resource 1");
}
}
}
};
t1.start();
t2.start();
}
}
OUTPUT:
Thread 1: locked resource 1
Thread 2: locked resource 2
Timeout due to heavy load
According to me this is the flow:
Thread1 enters the sync block on resource1 and sleeps
Thread2 enters the sync block on resource2 and sleeps
My doubt is that if Thread1 resumed execution before Thread2 since it slept before Thread2 ,then why didn't it enter the sync block on resource2since by that time Thread2 must have left the sync block on resource2 and avoided the Deadlock altogether ? Same is the doubt with why Thread2 entered the sync block on resource1after Thread1 left the same block before it?

My doubt is that if Thread1 resumed execution before Thread2 since it
slept before Thread2
Remember the first rule of multi-threading that if you are starting 2 threads, there is no guarantee that which thread will start first, so you cannot be sure whether your Thread1 will start and sleep first or Thread2 will start and sleep first.
then why didn't it enter the sync block on resource2since by that time
Thread2 must have left the sync block on resource2 and avoided the
Deadlock altogether ?
Notice that in both the threads, you are doing this:
get the lock of first object
sleep
get the lock of second object
release the lock of second object
release the lock of first object
So, both the threads will get the lock first and then sleep and there is very less chance that Thread2 would have not acquired the lock of resource2 by the time Thread1 will wake up, so almost everytime you get a deadlock.
I think this example is meant to demonstrate deadlock.
You "might" have not got the deadlock if:
In Thread2, you had try { Thread.sleep(100);} catch (Exception e) {} before synchronized (resource2) {. Because with this there is slight possibility that Thread1 would have acquired the lock of resource2 by the time Thread2 will wake up.
I think what you are missing to notice is that lock of both the objects will be acquired by the time both the threads will wake up.

The problem is that the threads you designed are not alone in you system, nothing guarantees that they will start immediately after you call start() nor that they will leave the sleep state synchronized. That's the whole point on deadlocked processes, because the system is constantly switching between processes (threads of processes) there might be a case where one process requires a resource that's being used by another process.You can never assume time constraints in processes unless you design a more complex synchronisation structure :/
As one of the comments explained,one of the reason for deadlocks to happen in general is that one process doesn't free the resources after it finishes using it. That's the case with you nested sync blocks.

Consider, Thread1 has completed these instructions
synchronized (resource1) {
System.out.println("Thread 1: locked resource 1");
try { Thread.sleep(100);} catch (Exception e) {}
Now goes to sleep and thread2 complete following instructions before going to sleep.
synchronized (resource2) {
System.out.println("Thread 2: locked resource 2");
try { Thread.sleep(100);} catch (Exception e) {}
Now when Thread1 awakes, it will try to execute
synchronized (resource2) {
System.out.println("Thread 1: locked resource 2");
}
but it can't complete it's execution because Thread2 has already taken lock on resource2. Since it is synchronized on resource2, it will not execute further unless Thread2 releases lock on resourse2. It is classic example of Hold and Wait.
Similarly, when Thread2 awakes it can not execute further because it is waiting for Resource1 which is locked by thread1

As pointed out in the comment section of the question, I missed out an important clue to the deadlock and that is the sync blocks are nested within each other and hence until the entire parent sync block gets completed the lock on parent resource wont be release. In order to verify, I have removed the nested braces and made the blocks independent and it seems the deadlock was avoided. Please let me know if my understanding was correct

Related

Questions about the concurrency‘s synchronized, how it works, what is the scope

I am trying to understand how java's synchronized works, and I have read some document, but would somebody helps check the correctness and also the questions
For the code block
public class MyWaitNotify3{
MonitorObject myMonitorObject = new MonitorObject();
boolean wasSignalled = false;
public void doWait(){
synchronized(myMonitorObject){
while(!wasSignalled){
try{
myMonitorObject.wait();
} catch(InterruptedException e){...}
}
//clear signal and continue running.
wasSignalled = false;
}
}
public void doNotify(){
synchronized(myMonitorObject){
wasSignalled = true;
myMonitorObject.notify();
}
}
}
MyWaitNotify3 inst1 = new MyWaitNotify3();
MyWaitNotify3 inst2 = new MyWaitNotify3();
If we create one thread with inst1, another thread with inst2
Then if we do thread1.doWait(), then the thread will hangs at the line "myMonitorObject.wait();"
The question is that the lock in scope of "dowait", "synchronized(myMonitorObject)", will this blocks thread2 from acquire the lock in "doNotify()"??
From my understanding, since they are two instances, thread2 cannot acquire the "synchronized(myMonitorObject)" in doWait, but would acquire the "synchronized(myMonitorObject)" in doNotify. Is that correct?
What will happens if we define
MyWaitNotify3 inst1 = new MyWaitNotify3();
thread1 = new Thread(inst1, "A");
thread2 = new Thread(inst1, "B");
The question is that the lock in scope of "dowait", "synchronized(myMonitorObject)", will this blocks thread2 from acquire the lock in "doNotify()"??
No, it won't. A thread will release the lock for the critical section (synchronized-block) when it goes into waiting state with wait in doWait. In that time, another thread can acquire that lock for the critical section in doNotify. When the waiting thread leaves the waiting state, it has to acquire the lock again.
However, when the thread in doWait is running, i.e. not blocked in wait, it will of course hold the current lock for the section, i.e. myMonitorObject, which will block another thread in doNotify.
You can imagine wait to be a point where a thread leaves the critical section, releases the lock, which enables others to acquire it, and as an entrance point for the critical section where the thread has to re-acquire the lock for it, which involves blocking.

Unexpected thread wakeup

I was expecting the second thread in the following example to hang, since it waits on an object with no corresponding notify. Instead, it falls through to the println, presumably due to a spurious wakeup.
public class Spurious {
public static void main(String[] args) {
Thread t1 = new Thread() {
public void run() {
System.out.println("Hey!");
}
};
Thread t2 = new Thread() {
public void run()
{
try {
synchronized (t1) {
t1.wait();
}
} catch (InterruptedException e) {
return;
}
System.out.println("Done.");
}
};
t1.start();
t2.start();
}
}
Output:
Hey!
Done.
On the other hand, if one removes the "Hey!" println from the first thread, the second thread will indeed hang. This happens on both MacOS and Linux.
Any idea why?
This is not a spurious wakeup, a spurious wakeup is caused by a race condition in the JVM. This is a race condition in your code.
The println keeps thread1 alive just long enough that thread2 can start waiting before thread1 terminates.
Once thread1 terminates it sends a notification to everything waiting on its monitor. thread2 receives the notification and ceases waiting.
Removing the println reduces the time needed for thread1 to finish so that thread1 has already finished by the time thread2 can start waiting on it. thread1 is no longer alive and its notification has already occurred before thread2 started waiting, so thread2 waits forever.
That threads send a notification when they die is documented in the API for Thread#join:
This implementation uses a loop of this.wait calls conditioned on this.isAlive. As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.
(For a thread to call notifyAll it has to hold the lock, if the other thread grabs the lock, it can keep the terminating thread alive and delay the notifyAll until the terminating thread can acquire the lock.)
The moral (well, one of the morals) is to always wait in a loop with a condition variable, see the Oracle tutorial. If you change Thread2 to look like this:
Thread t2 = new Thread() {
public void run()
{
try {
synchronized (t1) {
while (t1.isAlive()) {
t1.wait();
}
}
} catch (InterruptedException e) {
return;
}
System.out.println("Done.");
}
};
then thread2 should exit regardless of whether thread2 can start waiting before thread1 finishes.
Of course this is total toy example territory:
Don't extend Thread, use Runnable or Callable.
Don't lock on threads.
Don't start Threads, use Executors.
Prefer higher level concurrency constructs to wait/notify.
You're waiting on a Thread object. That's bad practice, that is explicitly discouraged in the javadoc of Thread (Thread.join, precisely).
The reason is that when you call thread.join() to block until the thread stops running, you're actually waiting on the thread. And when the thread stops running, it notifies in order to unblock all the callers of join().
Since you waited on the thread, you're implicitly being notified when the thread stops running.

Explicit locks acquisition order, between signaled threads and threads initially acquiring the lock, in Java

The Javadoc for the method Condition.newCondition() states "The ordering of lock reacquisition for threads returning from waiting methods is the same as for threads initially acquiring the lock, which is in the default case not specified, but for fair locks favors those threads that have been waiting the longest."
Does that mean that, with explicit locks, threads awakening from a condition compete for the lock acquisition together with the threads initially acquiring it, just as it occurs with implicit locks?
In other words, having two groups of threads, one who is trying to acquire the lock for the first time, and one who are trying to re-acquire the lock after having waited on a condition and being signaled, is the latter favored over the former on the lock acquisition?
Does the lock fairness value affects in any way the lock acquisition order of the these two groups?
In other words, having two groups of threads, one who is trying to acquire the lock for the first time, and one who are trying to re-acquire the lock after having waited on a condition and being signaled, is the latter favored over the former on the lock acquisition?
No, unless the Lock is “fair”, it’s most likely the opposite: typical implementations favor the thread just acquiring the Lock because it has less overhead to let that thread succeed instead of putting that thread to sleep and wake up another.
Does the lock fairness value affects in any way the lock acquisition order of the these two groups?
No, the lock acquisition makes no difference at that point. When a thread waiting on a Condition is signaled there might be other threads waiting longer for a first time acquisition. And a “fair” Lock will prefer the longest waiting thread.
For fair locks, a therad which reqcquires the lock after having singaled has to line up at the end of the lock queue.
The following short program demonstrates this behavior.
T1 acquires the lock first and then invokes await on a condition associated with this lock.
T2 then acquires the lock and waits until T3 tried to acquire the lock as well and then invokes a signal on the condition.
T3 waits some time before acuiring the lock which is hold by T2.
When T2 invokes signal, then T1 tries to reacquire the lock. When T2 releases the lock, then both T1 and T3 are competing for the lock, but T3 gets the lock first.
public class Test {
public static void main(String[] args) throws Exception {
final Lock r = new ReentrantLock(true);
final Condition c = r.newCondition();
Thread t1 = new Thread( () -> {
System.out.println("T1 try lock");
r.lock();
System.out.println("T1 got lock");
System.out.println("T1 invokes await and releases lock");
try { c.await(); } catch (InterruptedException e) { }
System.out.println("T1 reqcquired lock");
r.unlock();
} );
Thread t2 = new Thread( () -> {
sleep(50);
System.out.println("T2 try lock");
r.lock();
System.out.println("T2 got lock");
sleep(100);
c.signal();
System.out.println("T2 signaled");
sleep(100);
r.unlock();
} );
Thread t3 = new Thread( () -> {
sleep(100);
System.out.println("T3 try lock");
r.lock();
System.out.println("T3 got lock");
r.unlock();
} );
t1.start();
t2.start();
t3.start();
}
static void sleep(long millis) {
try { Thread.sleep(millis); } catch (InterruptedException e) { }
}
}
The output is
T1 try lock
T1 got lock
T1 invokes await and releases lock
T2 try lock
T2 got lock
T3 try lock
T2 signaled
T3 got lock
T1 got signal and reqcquired lock

wait(n) is acting different each time I change the position of synchronized keyword

Refer below code
public void acquire(){
synchronized(a){
print("acquire()");
try{
//Thread.sleep(5000);
synchronized(this){
wait(5000);
}
print("I have awoken");
print("" + a);
}catch(Exception e){
e.printStackTrace();
}
}
print("Leaving acquire()");
}
public void modify(int n){
print("Entered in modfy");
synchronized(a){
try{
//Thread.sleep(5000);
synchronized(this){
wait(5000);
}
this.a=n;
print("new value" + a);
}catch(Exception e){
e.printStackTrace();
}
}
}
And
final SynchoTest ttObj = new SynchoTest();
Thread A = new Thread(new Runnable(){
public void run() {
ttObj.acquire();
}
},"A");
Thread B = new Thread(new Runnable(){
public void run() {
ttObj.modify(97);
}
},"B");
A.start();
B.start();
As i know about wait(n), it pauses a thread until notify()/notifyAll() get called or the specified time n is over.
But...
In above methods if I directly use wait(n) as I used Thread.sleep(n),
I get runtime exception.
If I synchronize both methods instead of surrounding wait(n) with
synchronized block then I am not getting any exception but both
threads get blocked forever.
But if I do like I attached ie wait(n) surrounding with synchronized
block, it is working fine.
Please tell me why? Also tell me why is it not behaving different on positioning synchronized block if I use sleep(n) instead of wait(n)?
My question is about various result of wait(n) on various position of synchronized keyword.
#Gray
notify() or notifyAll(), and wait() must be in a synchronized block
for the object you are waiting on
explained me why I was getting run time exception by positioning synchronized block on various position.
Now please explain me, why
public void method(){
synchronized(a){
synchronized(this){
wait(n);
}
}
}
is working fine. But
public synchronized void method(){
synchronized(a){
wait(n);
}
}
is blocking my thread forever.
wait(n) and sleep(n) are completely different methods for pausing the execution of code:
wait(n) is called on an Object instance and will pause execution until the notify()/notifyAll() method is called on that instance or until the timer (the parameter) expires.
sleep(n) is called on a Thread object and essentially stops the world as far as that thread is concerned.
What your question comes down to is:
Do you want your object to act as a mutex, waiting for another piece of code to complete before continuing on it's own? Then use wait(n) with a corresponding notify()/notifyAll() in the other code.
Do you want to stop execution of the whole thread for a given timeframe? Then use Thread.sleep(n).
Maybe your code is not working because you didn't call start() on your threads? After you instantiate your threads you need to:
A.start();
B.start();
Also, you cannot do something like the following pattern. You cannot synchronize on a and then change the object of a. Well you can do it but I doubt that's what you want. Basically the a would change and someone else locking on a would lock on another object so would be able to be in the synchronized block as well. Very bad pattern.
synchronized (a) {
...
// not good
this.a = n;
}
Also, if you are not joining with the threads, then the main thread is going to continue on and not wait for A and B to finish. The JVM will wait for them to finish however since they are not daemon threads. And you have no guarantee that A will be called before B so the modify and acquire can happen in any order.
The difference between sleep(5000) and wait(5000) is that the wait can also be awoken by a call to notify() or notifyAll(), and wait() must be in a synchronized block for the object you are waiting on. synchronized also causes a memory barrier to be crossed which synchronizes the storage between multiple threads. It is more expensive because of that but in your case since you look to be sharing this.a then the memory barrier is required.
It is nothing about positioning synchronized keyword. You are facing problem since you locking other object and try to wait for another. Well #Gray has already been explained it, so not repeating it.
For your another problem, regarding why both threads are getting blocked;
Thread A: locks this [A: Runnable]
Thread A: locks a [A: Runnable]
Thread B: waiting for this [A: Runnable, B:BLOCKED]
Thread A: release this (meets wait) [A: TIMED WAITING, B:BLOCKED]
Thread B: lock this [A: TIMED WAITING, B: Runnable]
Thread B: waiting for a which is already locked by thread A [A: TIMED WAITING, B:BLOCKED]
Thread A: waiting for this which is locked by thread B [A: BLOCKED, B:BLOCKED]

Does notify/notifyall release the lock being held

I am confused a bit about wait and notify/notifyAll.
I know there is a lock for every java object. I know wait will release the lock for other thread. How about notify/notifyall? Does notify/notifyAll release the lock it is holding for other thread?
No -- notify/notifyAll don't release locks like wait does. The awakened thread can't run until the code which called notify releases its lock.
This is what the Javadoc says:
The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.
wait( ) tells the calling thread to give up the monitor and go to sleep until some other
thread enters the same monitor and calls notify( ).
notify( ) wakes up a thread that called wait( ) on the same object.
notifyAll( ) wakes up all the threads that called wait( ) on the same object. The
highest priority thread will run first.
I have to disagree with people who say notifyAll() releases the lock on the object over which waiting and notifying threads are being synchronized.
An example:
Consumer class contains a block:
synchronized(sharedObject){
if(sharedObject.isReadyToConsume() == false){
sharedObject.wait();
}else {
sharedObject.doTheThing();
System.out.println("consumer consuming...");
}
}
Scenario: Consumer class gets the lock on the sharedObject object, enters exclusively (it's inside the sync block) and sees that sharedObject has nothing ready yet (nothing to consume :) ) and it calls wait() method on the sharedObject. That way it releases the lock (stops the execution there!) and waits to be notified to continue when another Thread (Producer maybe) calls sharedObject.notify(); or sharedObject.notifyAll();. When it gets notified it continues from the wait() line
It's the sharedObject that keeps track of threads that asked it to be notified. When some Thread calls sharedObject.notifyAll() method the sharedObject will notify the waiting threads to wake up...
Now, the tricky part is that a thread naturally releases the lock of the object when it reaches the end of its synchronized(sharedObject){} block. THe question is what happens if I call notifyAll() in that block??? notifyAll() wakes up the waiting threads, but the lock is still owned by the Thread that has just call notifyAll()
Look at the Producer snippet:
synchronized(sharedObject){
//We are exlusively working with sharedObject and noone can enter it
[... changing the object ...]
sharedObject.notifyAll(); //notifying the waiting threads to wake up
Thread.sleep(1000); //Telling the current thread to go to sleep. It's holding the LOCK
System.out.println("awake...");
}
If notifyAll() would release the lock then the "awake..." would get printed out after the Consumer classes already start working with the sharedObject. This is not the case... The output shows that the Consumer is consuming the sharedObject after the Producer exits its sync block...
wait() - releases the lock and continues on the next line when it gets notified
notify(), notifyAll() - don't release the lock. They simply make waiting threads runnable again (not idle). They will have the right to enter when the
current thread reaches the end of its sync block and the Thread
scheduleder tells them that the lock has been released. The fight for
the lock begins again
Lets say bunch of Readers wants to read updated Value of certain Resource, which is going to be updated by Writer. Then how Reader knows that Resource Fields have been updated by Writer.
Therefore to Synchronize such cases between Readers and Writers on common resource, three final methods of Object class have been used.
wait()
notify()
notifyAll()
Wait : Readers wants to read updated value of resource, they register with resource object i.e when update happens on same object and when Writer notify it, readers will try to acquire lock on resource and read the updated resource.
- Wait only being invoked when Reader have Lock Object, here in our case it is resource.
- Once wait method is called, Reader releases the Lock Object.
- Now Only for the same registered Object(resource) Reader will get notification signals.
- If Reader invokes wait on Object, which is different from Object Writer used for sending notification, Reader will never gets the notification signal.
- Once Reader(s) are notified, now Reader(s) will try to content for the Lock(one of them gets the lock) read the updated value of resource. Similarly other Readers also gets turn to acquire lock and read the updated value.
- Once Reader read the updated value, perform there Business Logic and come out from Synchronized Block, Reader will release the lock so that other Readers can acquire it.
Notify: Writer enters the Synchronized Block, after acquiring lock performs his Business Logic, update the resource Object, once resource Object is updated it will notify the waiting threads(Readers) whom are waiting on same Lock.
- Notify signal to only one waiting Thread, which is decided by underlying Java Thread Manager
- Once Writer signals notify(), then it doesn't means Reader rushed immediately to read the updates values. Firstly writer must release the Lock, which it will do once it comes out of Synchronized block.Once Lock is being released and waiting threads are notified, then [In case of notify()] notified Thread will acquire the Lock[Released by Writer] and then enter the Synchronized Block and completes from where he left[i.e statements after wait()].
Notify-All: In notifyAll, all threads who are registered with resource lock, will get the notifications.
- Once notifyAll() is triggered, all threads waiting on same lock will get the signal and are ready in contention to acquire the lock.
- Once Writer finishes its Job and release the Lock, Any one Reader will acquire the lock[which Thread, again decided by underlying Java Thread Manager Implementation].
- Once the Reader gets the Lock, it will enter in Synchronized Block, where he left[i.e after wait() method] performs it tasks and on completing the Synchronized Block releases the Lock.
- Now Other remaining Threads will try to acquire the Lock, anyone of them will get it, enters synchronized block, completes its task and then release the Lock.
- This process will keep on till all Registered Readers complete there Job.
Now we will see the Code for it. Also we will discuss the Code also. :
Basic Overview Of code : It consists of Three classes
Resource Class : On which Lock will be acquired and wait() and notify(), notifyAll() will be invoked.
ReaderTask : Implements Runnable interface, implies readers jobs, wants to read updated Value of resource object.
WriterTask : Implements Runnable interface, implies writer jobs, will update the resource object and notify registered waiting threads.
Demo Class: which will create Let say 3 Readers and 1 Writer Thread, Bind Respective Tasks to them and start the threads.
Resource.java
public class Resource {
private String mesg;
public void setMesg(String mesg){
this.mesg =mesg;
}
public String getMesg(){
return this.mesg;
}
}
WaitThreadTask.java
public class WaitThreadTask implements Runnable {
private Resource resource;
public WaitThreadTask(Resource resource){
this.resource = resource;
}
#Override
public void run() {
// TODO Auto-generated method stub
synchronized(resource){
System.out.println("Before Reading Updated Value By : " +Thread.currentThread().getName() );
//We need to Take care to get the updated value, so waiting for writer thread to update value.
try {
//Release resource Lock & wait till any notification from Writer.
resource.wait();
System.out.println("Waiting is Over For : "+ Thread.currentThread().getName());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Read Updated Value
System.out.println("Updated Value of Resource Mesg :" + resource.getMesg() + " Read By :" +Thread.currentThread().getName());
}
}
}
WriterThreadTask.java
public class WriterThreadTask implements Runnable{
private Resource resource;
public WriterThreadTask(Resource resource){
this.resource = resource;
}
#Override
public void run() {
// TODO Auto-generated method stub
synchronized(resource){
System.out.println("Before Updating Resource By : " + Thread.currentThread().getName());
//Updating resource Object Message
resource.setMesg("Hi How are You !!!");
resource.notify();
//resource.notifyAll();
//Once Writer Comes Out from Synch Block, Readers will Content to read the values.
System.out.println("Task Done By Writer Thread.");
}
}
}
ThreadDemo.java
public class ThreadDemo {
public static void main(String args[]){
//Create Single Resource Object, which can act as Lock on Writer and Readers.
Resource lock = new Resource();
//Three Readers and One Writer runnable Tasks.
Runnable taskR1 = new WaitThreadTask(lock);
Runnable taskR2 = new WaitThreadTask(lock);
Runnable taskR3 = new WaitThreadTask(lock);
Runnable taskW1 = new WriterThreadTask(lock);
Thread t1 = new Thread(taskR1, "Reader1");
Thread t2 = new Thread(taskR2, "Reader2");
Thread t3 = new Thread(taskR3, "Reader3");
Thread t4 = new Thread(taskW1, "Writer1");
t1.start();
t2.start();
t3.start();
/*try{
Thread.sleep(5000);
} catch(InterruptedException e){
e.printStackTrace();
}*/
t4.start();
}
}
Code Observations :
Both notify()/notifyAll() and wait() : works only on the Lock Objects they already acquire. For example : Synchornized(ObjectA) {......// ... // ObjectB.wait() or ObjectB.notify() or ObjectB.notifyAll() ...} then It will throw IllegalMonitorStateException. Therefore care must be taken that lock must be acquired before calling any of above three methods with same lock.Even If you simply write notify() or wait() or notifyAll(), then still it will throw IllegalMonitorStateException because [It suggest lock must be acquired on this Object, again which is not the case].
Reader will only able to receive signals on which same notification is send. If wait is happening on Object which is different from Object on which notification is being send, then Readers will never get the notification and hence they will wait forever.
Readers which are registered before Writer able to send the notification, Only those readers will get it. Because if Writer sends notification first, before reader registered to Object, they will not receive the signals as Signals are already being missed : Missed Signals
Reader and Writer should acquire Lock on same Object and should invoke wait/notification signals on same Object. If the above code is modified as, instead of using resource for locks and wait and notify, If we use this. What will happen ? Well .. All readers will wait forever, Because readers registered with different Objects of WaitThreadTask and writer notify on WriterThreadTask. Therefore none of the Reader will receive notification signals, as they registered to receive signals on respective WaitThreadTask Object and not on WriterThreadTask Object.
public class ProducerConsumerInJava {
public static void main(String args[]) {
System.out.println("How to use wait and notify method in Java");
System.out.println("Solving Producer Consumper Problem");
Queue<Integer> buffer = new LinkedList<>();
int maxSize = 10;
Thread producer = new Producer(buffer, maxSize, "PRODUCER");
Thread consumer = new Consumer(buffer, maxSize, "CONSUMER");
producer.start();
consumer.start();
}
}
class Producer extends Thread {
private Queue<Integer> queue;
private int maxSize;
public Producer(Queue<Integer> queue, int maxSize, String name){
super(name); this.queue = queue; this.maxSize = maxSize;
}
public void run() {
while (true) {
synchronized (queue) {
while (queue.size() == maxSize) {
try {
System.out .println("Queue is full, " +
"Producer thread waiting for " + "consumer to take
something from queue");
queue.wait();
} catch (Exception ex) {
ex.printStackTrace();
}
}
Random random = new Random();
int i = random.nextInt();
System.out.println("Producing value : " + i);
queue.add(i);
queue.notifyAll();
}
}
}
}
class Consumer extends Thread {
private Queue<Integer> queue;
private int maxSize;
public Consumer(Queue<Integer> queue, int maxSize, String name){
super(name); this.queue = queue; this.maxSize = maxSize;
}
public void run() {
while (true) {
synchronized (queue) {
while (queue.isEmpty()) {
try {
System.out .println("Queue is empty," +
"Consumer thread is waiting" +
" for producer thread to put something in queue");
queue.wait();
} catch (Exception ex) {
ex.printStackTrace();
}
}
System.out.println("Consuming value : " + queue.remove());
queue.notifyAll();
}
}
}
}
This is an example of Consumer and Producer program.
Output of the above program after execution is written below:
How to use wait and notify
method in Java Solving Producer Consumper Problem
Queue is empty,Consumer thread is waiting for producer thread to put
something in queue
Producing value : -1692411980
Producing value : 285310787
Producing value : -1045894970
Producing value : 2140997307
Producing value : 1379699468
Producing value : 912077154
Producing value : -1635438928
Producing value : -500696499
Producing value : -1985700664
Producing value : 961945684
Queue is full, Producer thread waiting for consumer to take something from
queue Consuming value : -1692411980
Consuming value : 285310787
Consuming value : -1045894970
Consuming value : 2140997307
Consuming value : 1379699468
Consuming value : 912077154
Consuming value : -1635438928
Consuming value : -500696499
Consuming value : -1985700664
Consuming value : 961945684
Queue is empty,Consumer thread is waiting for producer thread to put
something in queue
Producing value : 118213849
So, what we can conclude is, notifyAll() or notify() will not release the lock. have a look at the output, Producing value and Consuming value are not printed alternatively i.e there are printed separately.
Hence, notify/ notifyAll will not release lock
Read more: http://javarevisited.blogspot.com/2015/07/how-to-use-wait-notify-and-notifyall-in.html#ixzz57kdToLX6
To clarify my understanding and to provide an example for all to show when the lock is released, I have added print statements to the following code after the call to notify()/NotifyAll():
class ThreadDemo {
public static void main(String[] args) {
Shared s = new Shared();
new Producer(s).start();
new Consumer(s).start();
}
}
class Shared {
private char c = '\u0000';
private boolean writeable = true;
synchronized void setSharedChar(char c) {
while (!writeable)
try {
wait();
} catch (InterruptedException e) {
}
this.c = c;
writeable = false;
notifyAll();
System.out.println("setSharedChar notify() called - still in synchronized block.");
}
synchronized char getSharedChar() {
while (writeable)
try {
wait();
} catch (InterruptedException e) {
}
writeable = true;
notifyAll();
System.out.println("getSharedChar notify() called - still in synchronized block.");
return c;
}
}
class Producer extends Thread {
private Shared s;
Producer(Shared s) {
this.s = s;
}
public void run() {
System.out.println("Starting producer thread.");
for (char ch = 'A'; ch <= 'Z'; ch++) {
System.out.println("Producer thread getting ready to create a char.");
try {
Thread.sleep((int) (Math.random() * 1000));
} catch (InterruptedException e) {
}
s.setSharedChar(ch);
System.out.println(ch + " produced by producer.");
}
}
}
class Consumer extends Thread {
private Shared s;
Consumer(Shared s) {
this.s = s;
}
public void run() {
System.out.println("Starting consumer thread.");
char ch;
do {
System.out.println("Consumer thread getting ready to read a char.");
try {
Thread.sleep((int) (Math.random() * 1000));
} catch (InterruptedException e) {
}
ch = s.getSharedChar();
System.out.println(ch + " consumed by consumer.");
} while (ch != 'Z');
}
}
When I ran this example enough times, there was a point where I did eventually see the output of the program show:
...
F produced by producer.
Producer thread getting ready to create a char.
getSharedChar notify() called - still in synchronized block.
F consumed by consumer.
Consumer thread getting ready to read a char.
setSharedChar notify() called - still in synchronized block.
G produced by producer.
Producer thread getting ready to create a char.
getSharedChar notify() called - still in synchronized block.
setSharedChar notify() called - still in synchronized block.
G consumed by consumer.
Since the output getSharedChar is able to appear before setSharedChar, it appears that the lock is being released immediately or not required to reenter the synchronized getSharedChar() function by the call to notifyAll(). The lock may still be in place, but if you can reenter the function without it, what is the difference?
I was able to see similar output substituting notify() for notifyAll(). This was done on Java 1.7.0_15 on a 64 bit Windows 7 system.
wait(): Virtually every object in Java posses a monitor, to enter inside any synchronized block a thread has to first acquire this monitor and then only he can enter this synchronized block. As critical section of the code is executed by a single thread at a time so it has a great impact on overall performance of the application. So in place of holding the resource(monitor) threads can be asked to leave the critical section and wait for some time. To achieve this behaviour Java has provided a wait() api directly in Object class.
So any time a thread encounter a wait() API, it drops the current monitor plus all other monitors it holds and go to waiting state linked the current object. Its important to understand that that went to the waiting state in the context of object for which thread acquired the monitor first.. In a conceptual way i explain, every object holds a container house where all waiting threads are held.
There are multiple ways a Thread can come out of this container house of Object. Lets see..
When another thread comes and rings the bell once, In Java by calling
notify() method on the same object.
When another thread comes and rings multiple time, one of the Thread
gets a chance to come out of Object’s container house. In Java we can
do this by calling notifyAll() on the same object.
If we have the reference of the Thread waiting in container house.
Calling interrupt() on the Thread object pops it out of waiting state
and brings it the exception block of the Object.
There are overloaded wait(long milliseconds) and wait(long millSec,
int nanos) methods. As the time over the Thread is eligible to come
out of waiting state and contest for Object monitor again. In case
Thread fails to acquire the monitor after timeout also then it has to
wait for notify() calls only.
notify(): If the objects container house has multiple threads in waiting state then calling notify() on the this object given chance to one the thread to proceed. But after coming out of the waiting state the thread still has to contest for the object monitor and if it succeeds in getting the monitor it continue its execution otherwise thread will come back to waiting state. So notify() also has to be called from the synchronized block. If the notify() is not called from synchronized context then it thorws IllegalMonitorStateException.
notifyAll(): Calling notifyAll() on the Object makes sure all the threads in Object container house are awakened but once awakened they have to compete with each other or any other thread wants to acquire the object monitor. Which ever thread succeeds continue its executions others have to go back to waiting state and settle in object container house. As notify(), notifyAll() should also be called in synchronized context.
Explanation Taken from http://coder2design.com/thread-communication/
Calling notify() method on an object changes the state of the waiting threads.
The notifying thread only releases the lock once it completes the execution of its synchronized code on the lock object it is going to release.
So here's how it is:
wait()
If a thread calls wait() method on an object, the thread IMMEDIATELY releases the lock of that object and goes into waiting state.
notify()
But when a thread calls notify() method on an object, the thread does not release the lock of that object immediately, if the thread have some more job to do (i.e code to execute after notify() call). If the execution of the synchronized code is completed or there are no statements after notify(), then the thread releases the lock for waken up threads from waiting state.

Categories