Sleeping thread losses ownership of monitor lock? - java

I wanted to verify in my own eyes the different between sleep and wait.
Wait can only be done in a synchronized block because it releases the ownership of the monitor lock.
While sleep is not related to the monitor lock and a thread that is already the owner of the monitor lock shouldn't lose its ownership if sleeping.
For that i made a test:
Steps:
Started a thread that waits in a synched block for 5 secs.
Waited 3 secs and started another thread that acquires the monitor lock (because Thread-A is waiting) and simply sleeps for 5 secs while holding the monitor lock.
Expected result:
Thread - A will only re-acquire the lock after 8 seconds, When Thread - B finally releases the monitor lock by exiting the synch block.
Actual result.
Thread - A acquires the monitor lock after 5 seconds.
Can some1 explain to me what happened here?
public static void main(String[] args) {
Runnable r1 = new Runnable() {
#Override
public void run() {
System.out.println("r1 before synch block");
synchronized (this) {
System.out.println("r1 entered synch block");
try {
wait(5000);
System.out.println("r1 finished waiting");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Runnable r2 = new Runnable() {
#Override
public void run() {
System.out.println("r2 before synch block");
synchronized (this) {
System.out.println("r2 entered synch block");
try {
Thread.currentThread();
Thread.sleep(5000);
//wait(5000);
System.out.println("r2 finished waiting");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
try {
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
Thread.currentThread();
Thread.sleep(3000);
t2.start();
t1.join();
t2.join();
System.out.println(Thread.currentThread().getName() + " Finished joining");
} catch (Exception e) {
e.printStackTrace();
}
}
EDIT:
Ok I understand my error - I waiting on this - r1/r2 and not on the same object.
Now I changed it and both acquire on the same object - The class instance of Main.
1. r1 acquires ownership of the monitor lock of Main.this
2. r1 Releases it.
3. When r1 tries to re-acquire it I get an exception:
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at Main$1.run(Main.java:28)
at java.lang.Thread.run(Unknown Source)
on synchronized (Main.this)
What is the problem here?
public static void main(String[] args) {
Main main = new Main();
main.test();
}
public void test() {
Runnable r1 = new Runnable() {
#Override
public void run() {
System.out.println("r1 before synch block");
synchronized (Main.this) {
System.out.println("r1 entered synch block");
try {
wait(5000);
System.out.println("r1 finished waiting");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Runnable r2 = new Runnable() {
#Override
public void run() {
System.out.println("r2 before synch block");
synchronized (Main.this) {
System.out.println("r2 entered synch block");
try {
Thread.currentThread();
Thread.sleep(5000);
//wait(5000);
System.out.println("r2 finished waiting");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
try {
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
Thread.currentThread();
Thread.sleep(3000);
t2.start();
t1.join();
t2.join();
System.out.println(Thread.currentThread().getName() + " Finished joining");
} catch (Exception e) {
e.printStackTrace();
}
}

The two threads actually hold two different locks. Say your class name is MyClass, change two lines of synchronized (this) to synchronized (MyClass.this), that makes the two threads to hold same lock.

here's a much better way to make the test work , and show that it works .
your problem was that you didn't wait correctly and used Thread.currentThread() for no reason .
btw, in case you want to use signalling of the wait-notifier mechanism without losing the signal , i suggest you read this link.
public class MAIN
{
public static void main(final String[] args)
{
final Object sync =new Object();
final long startTime=System.currentTimeMillis();
final Runnable r1=new Runnable()
{
#Override
public void run()
{
System.out.println((System.currentTimeMillis()-startTime)/1000+": r1 before synch block");
synchronized(sync)
{
System.out.println((System.currentTimeMillis()-startTime)/1000+": r1 entered synch block");
try
{
sync.wait(5000);
System.out.println((System.currentTimeMillis()-startTime)/1000+": r1 finished waiting");
}
catch(final InterruptedException e)
{
e.printStackTrace();
}
}
System.out.println((System.currentTimeMillis()-startTime)/1000+": r1 exited synch block");
}
};
final Runnable r2=new Runnable()
{
#Override
public void run()
{
System.out.println((System.currentTimeMillis()-startTime)/1000+": r2 before synch block");
synchronized(sync)
{
System.out.println((System.currentTimeMillis()-startTime)/1000+": r2 entered synch block");
try
{
Thread.sleep(5000);
System.out.println((System.currentTimeMillis()-startTime)/1000+": r2 finished waiting");
}
catch(final InterruptedException e)
{
e.printStackTrace();
}
}
System.out.println((System.currentTimeMillis()-startTime)/1000+": r2 exited synch block");
}
};
try
{
final Thread t1=new Thread(r1);
final Thread t2=new Thread(r2);
t1.start();
Thread.sleep(3000);
t2.start();
t1.join();
t2.join();
System.out.println((System.currentTimeMillis()-startTime)/1000+": Finished joining");
}
catch(final Exception e)
{
e.printStackTrace();
}
}
}

Related

Proper use of wait and notify methods in Java threading

I am new to Java multithreading. I created simple producer-consumer pattern using wait and notify but my producer is getting called only once in tbe starting.
public class ThreadApp {
public static void main(String[] args) throws InterruptedException {
ProducerConsumerWorldp = new ProducerConsumerWorld();
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
try {
p.producer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
try {
p.consumer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
}
}
class ProducerConsumerWorld{
public void producer() throws InterruptedException{
synchronized (this) {
while(true){
System.out.println("Producer thread started running");
wait();
System.out.println("Resumed Producing");
}
}
}
public void consumer() throws InterruptedException{
synchronized (this) {
while(true){
Thread.sleep(2000);
System.out.println("Consumer thread started running");
System.out.println("Press enter to consume all and start producing");
Scanner s = new Scanner(System.in);
s.nextLine();
notify();
Thread.sleep(2000);
System.out.println("consumed all");
}
}
}
}
I am creating separate threads for producer and consumer. Producer thread only gets called in the starting and then after it is never getting executed.
I tried two option to overcome this issue. first I put while condition outside of synchronized block second is given below.
class ProducerConsumerWorld{
public void producer() throws InterruptedException{
synchronized (this) {
while(true){
System.out.println("Producer thread started running");
notify();
wait();
System.out.println("Resumed Producing");
}
}
}
public void consumer() throws InterruptedException{
synchronized (this) {
while(true){
Thread.sleep(2000);
System.out.println("Consumer thread started running");
System.out.println("Press enter to consume all and start producing");
Scanner s = new Scanner(System.in);
s.nextLine();
notify();
Thread.sleep(2000);
System.out.println("consumed all");
wait();
}
}
}
}
Both works great. Which one the of the appropriate solution to use ? I am still unable to figure out why the code I put in question is not working properly.
I am still unable to figure out why the code I put in question is not working properly
The wait() in producer() releases the monitor which allows consumer() to enter its synchronized block. Then the wait() in producer() starts waiting till consumer() calls notify() and releases the monitor (i.e. exits its synchronized block). You never exit synchronized in consumer() therefore the wait() in producer() is blocked forever
I am still unable to figure out why the code I put in question is not
working properly
I've managed to fix your code, and I've attached below the fixed code snippet.
I've introduced a boolean instance variable named isConsumed for the ProducerConsumerWorld. In doing so, what essentially happens is that after Producer Thread produces, he updates the state of isConsumed to false, since he has produced something which is yet to be consumed. Afterwards, the producer notifies the the Consumer thread, that Producer has finished producing. Next, it invokes wait() on the ProducerConsumerWorld which releases Producer's lock on ProducerConsumerWorld. Then, it waits for the lock on ProducerConsumerWorld.
Meanwhile, the Consumer Thead acquires the lock on ProducerConsumerWorld, which allows it to enter the consumer method, where it checks if there is produce yet to be consumed. If so, it consumes and updates the isConsumed variable to true, and notifies the produce has been consumed. Then the consumer proceeds to releases its lock on ProducerConsumerWorld by calling wait(), and waits to reacquire the lock on ProducerConsumerWorld after Producer has consumed.
Note:
Calling notify() doesn't release a lock until the thread moves out of the synchronized block, or wait() is called, thus releasing the lock.
Source: Oracle's OCA/OCP Java SE 7 Study Guide Page 760
Code:
import java.util.Scanner;
public class ThreadApp {
public static void main(String[] args) throws InterruptedException {
ProducerConsumerWorld p = new ProducerConsumerWorld();
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
try {
p.producer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
try {
p.consumer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
}
}
class ProducerConsumerWorld{
boolean consumed = false;
public void producer() throws InterruptedException{
System.out.println("Producer thread started running");
synchronized (this) {
while(this.consumed == true){ // Consumer has consumed and is waiting for produce
System.out.println("Resumed Producing");
this.consumed = false;
notify();
wait();
}
}
}
public void consumer() throws InterruptedException{
synchronized (this) {
while(this.consumed == false){
Thread.sleep(2000);
System.out.println("Consumer thread started running");
System.out.println("Press enter to consume all and start producing");
Scanner s = new Scanner(System.in);
s.nextLine();
this.consumed = true;
System.out.println("consumed all");
notify();
wait();
}
}
}
}
This gives me an output like,

Wait And Notify IllegalMonitorStateException Anonymous Class

According to How to use wait and notify in Java? I have to synchronized on the same object to call notify.
I have synchronized on the same haveCoffee object. Why I am getting IllegalMonitorStateException when I call the notify method ?
I am Sleeping
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at com.example.concurrent.basic.WaitAndNotify$2.run(WaitAndNotify.java:42)
in the following code:
public class WaitAndNotify {
public static void main(String[] args) {
Thread haveCoffee = new Thread() {
public void run() {
synchronized (this) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print("I am awake and ready to have coffee");
}
}
};
Thread me = new Thread() {
public void run() {
synchronized (haveCoffee) {
try {
System.out.print("I am Sleeping");
Thread.sleep(4000);
notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
haveCoffee.start();
me.start();
}
}
On the first Thread, you call wait on an object while having its monitor (the object being this haveCoffee).
However, on the second thread, you call notify() on me, while having the monitor of haveCoffee.
This should work:
public class WaitAndNotify {
public static void main(String[] args) {
final Thread haveCoffee = new Thread() {
public void run() {
synchronized (this) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print("I am awake and ready to have coffee");
}
}
};
Thread me = new Thread() {
public void run() {
synchronized (haveCoffee) {
try {
System.out.print("I am Sleeping");
Thread.sleep(4000);
haveCoffee.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
haveCoffee.start();
me.start();
}
}
From oracle documentation page,
public class IllegalMonitorStateException
extends RuntimeException
Thrown to indicate that a thread has attempted to wait on an object's monitor or to notify other threads waiting on an object's monitor without owning the specified monitor.
Whenever you get this exception, just go through your code and check wait() and notify() calls and the object on which these calls have been invoked. You can easily figure out what went wrong.
EDIT:
wait() or notify() calls have to be invoked on object once you get monitor on that object.
You should be calling
haveCoffee.notify()
instead of just
notify().
If you invoke just notify() it calls the notify() method on the this object which is the second thread me where as you have synchronized on haveCoffee thread and that is the reason for exception you are seeing.
So the code in thread2 me should looks like:
synchronized (haveCoffee) {
try {
System.out.print("I am Sleeping");
Thread.sleep(4000);
haveCoffee.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

Make threads start in particular order in Java

I would like to make a simple thread program that starts 3 threads in order 1,2,3 and after that stops in order 3,2,1 just by using the sleep() method. However, everytime the threads start in different order.
class Thread1 extends Thread{
public void run(){
System.out.println("Thread 1 running...");
try {
this.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Thread 1 has terminated");
}
}
class Thread2 extends Thread {
public void run(){
System.out.println("Thread 2 running...");
try {
this.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Thread 2 has terminated");
}
}
class Thread3 extends Thread {
public void run(){
System.out.println("Thread 3 running...");
try {
this.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Thread 3 has terminated");
}
}
public static void main(String[] args) throws InterruptedException {
Thread tr1 = new Thread1();
Thread tr2 = new Thread2();
Thread tr3 = new Thread3();
tr1.start();
tr2.start();
tr3.start();
}
current output:
Thread 1 running...
Thread 3 running...
Thread 2 running...
Thread 3 has terminated
Thread 2 has terminated
Thread 1 has terminated
desired output:
Thread 1 running...
Thread 2 running...
Thread 3 running...
Thread 3 has terminated
Thread 2 has terminated
Thread 1 has terminated
Your threads are started in right order, but output can be wrong because output messages arrive concurrently. You should move messaging into the main thread:
public static void main(String[] args) throws InterruptedException {
Thread tr1 = new Thread1();
Thread tr2 = new Thread2();
Thread tr3 = new Thread3();
tr1.start();
System.out.println("Thread 1 started");
tr2.start();
System.out.println("Thread 2 started");
tr3.start();
System.out.println("Thread 3 started");
}
You can make Util class, witch must be thread safe, and make synchronized method to print.
public class Utils {
public static synchronized void printStuff(String msg) {
System.out.println(msg);
}
}
Now in Thread1, Thread2 and Thread3 use this Utils.printStuff("Text") to print in console.

is this a thread deadlock

I wanted to intentionally do/test java thread deadlock state so I made a following sample code:
public class TestDeadLock extends Thread{
private Integer a=new Integer(9);
public void run(){
if(Thread.currentThread().getName().equals("t1")){
XXXX();
}
else{
ZZZZ();
}
}
public void XXXX(){
System.out.println("inside XXXX");
synchronized(a){
a++;
ZZZZ();
}
System.out.println("xxxxxxxxxxxxxxxxxxx");
//ZZZZ();
}
public synchronized void ZZZZ(){
System.out.println("inside ZZZZ");
synchronized(a){
a--;
XXXX();
}
System.out.println("zzzzzzzzzzzzzzzzzzzzz");
}
public static void main(String[] args) throws InterruptedException {
TestDeadLock tdl=new TestDeadLock();
Thread t1=new Thread(tdl);
Thread t2=new Thread(tdl);
t1.setName("t1");
t2.setName("t2");
t1.start();
t2.start();
Thread.sleep(1000);
System.out.println("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="+tdl.a);
}
}
The output came out to be like :
inside XXXX
inside ZZZZ
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=10
output is NOT exiting.
I wanted to know, was it due to threads reached Dead Lock state? Is it a right example to experience Dead Lock. Suggest or correct me if I am wrong.
No, you are not experiencing a dead lock. You are encountering a StackOverflowError because you are running into an infinite loop.
Note that your method
public synchronized void ZZZZ() {
System.out.println("inside ZZZZ");
XXXX(); // run-time exception
}
is equivalent to
public void ZZZZ() {
synchronized(this) {
System.out.println("inside ZZZZ");
XXXX(); // run-time exception
}
}
You are not causing a dead lock because you are working on two different instances.
Thread 1 locks t1, thread 2 locks t2.
Your ZZZZ() method contains a call to XXXX() method and vice-versa.
Thus, you have created a never-ending chain of calls that goes: ZZZZ() -> XXXX() -> ZZZZ() -> XXXX() -> etc.
Eventually, your stack will grow too large from all the nested method calls that get pushed onto the stack. Hence, the exceptions that you are getting.
Try this example:
public class TestThread {
public static Object Lock1 = new Object();
public static Object Lock2 = new Object();
public static void main(String args[]) {
ThreadDemo1 T1 = new ThreadDemo1();
ThreadDemo2 T2 = new ThreadDemo2();
T1.start();
T2.start();
}
private static class ThreadDemo1 extends Thread {
public void run() {
synchronized (Lock1) {
System.out.println("Thread 1: Holding lock 1...");
try { Thread.sleep(10); }
catch (InterruptedException e) {}
System.out.println("Thread 1: Waiting for lock 2...");
synchronized (Lock2) {
System.out.println("Thread 1: Holding lock 1 & 2...");
}
}
}
}
private static class ThreadDemo2 extends Thread {
public void run() {
synchronized (Lock2) {
System.out.println("Thread 2: Holding lock 2...");
try { Thread.sleep(10); }
catch (InterruptedException e) {}
System.out.println("Thread 2: Waiting for lock 1...");
synchronized (Lock1) {
System.out.println("Thread 2: Holding lock 1 & 2...");
}
}
}
}
}
This accurately shows threads reaching deadlock.
Here is the solution:
public class TestThread {
public static Object Lock1 = new Object();
public static Object Lock2 = new Object();
public static void main(String args[]) {
ThreadDemo1 T1 = new ThreadDemo1();
ThreadDemo2 T2 = new ThreadDemo2();
T1.start();
T2.start();
}
private static class ThreadDemo1 extends Thread {
public void run() {
synchronized (Lock1) {
System.out.println("Thread 1: Holding lock 1...");
try { Thread.sleep(10); }
catch (InterruptedException e) {}
System.out.println("Thread 1: Waiting for lock 2...");
synchronized (Lock2) {
System.out.println("Thread 1: Holding lock 1 & 2...");
}
}
}
}
private static class ThreadDemo2 extends Thread {
public void run() {
synchronized (Lock1) {
System.out.println("Thread 2: Holding lock 1...");
try { Thread.sleep(10); }
catch (InterruptedException e) {}
System.out.println("Thread 2: Waiting for lock 2...");
synchronized (Lock2) {
System.out.println("Thread 2: Holding lock 1 & 2...");
}
}
}
}
}
Source: http://www.tutorialspoint.com/java/java_thread_deadlock.htm
Example given by Jase Pellerin is a good example of dead lock but it has one mistake (Sorry Jase Pellerin , i am sure you did it unintetionally) . Here, both methods are trying to get hold of Lock1 first and then Lock2. I think it should be other way around.
Thread1{
synchronized (Lock1) {
synchronized (Lock2) {}
}
}
Thread2{
synchronized (Lock2) {
synchronized (Lock1) {}
}
}

Using Interrupt method

public class TwoThreads {
private static Object resource = new Object();
private static void delay(long n) {
try
{
Thread.sleep(n);
}
catch (Exception e)
{
e.printStackTrace();
}
}
public static void main(String[] args) {
System.out.print("StartMain ");
new Thread1().start();
delay(1000); //dealay 1
Thread t2 = new Thread2();
t2.start();
delay(1000); // delay 2
t2.interrupt(); //step 7
delay(1000); //delay 3
System.out.print("EndMain ");
}
static class Thread1 extends Thread {
public void run() {
synchronized (resource) {
System.out.print("Startl ");
delay(6000);
System.out.print("End1 ");
}
}
}
static class Thread2 extends Thread {
public void run() {
synchronized (resource) {
System.out.print("Start2 ");
delay(2000);
System.out.print("End2 ");
}
}
}
}
At step 7 (as I have marked), main thread calls interrupt() on thread t2, but as it was waiting to acquire the lock on a resource, it doesn't throw any exception. After that, main thread prints "End Main" after waiting 1000 ns. In other words, main thread has completed its task, so what triggers t2.interrupt() again because it throws exception after that?
Here is how your program runs, with timestamps:
0000 StartMain
0000 Startl
3000 EndMain
6000 End1
6000 Start2
6000 End2
Why (timestamps in brackets)?
[0000] main launches Thread1, which acquires a lock and sleeps for 6 seconds
[1000] main launches Thread2, which can't acquire the lock held by Thread1 for 6 seconds
[2000] main interrupts Thread2 setting its interrupted flag to true, but Thread2 is waiting for a lock and does not do anything about it
[3000] main ends
[6000] Thread1 finishes sleeping and releases the lock
[6000] Thread2 can acquire it and starts to sleep (its interrupted flag is still on)
[6000] sleep detects that Thread2 has been interrupted and throws an exception immediately
[6000] Thread2 finishes, allowing the JVM to exit
You need a ReentrantLock.
public class TwoThreads {
private static Lock lock = new ReentrantLock();
private static void delay(long n) {
try {
Thread.sleep(n);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
System.out.print("StartMain ");
new Thread1().start();
delay(1000); //dealay 1
Thread t2 = new Thread2();
t2.start();
delay(1000); // delay 2
t2.interrupt(); //step 7
delay(1000); //delay 3
System.out.print("EndMain ");
}
static class Thread1 extends Thread {
public void run() {
try {
lock.lockInterruptibly();
try {
System.out.print("Startl ");
delay(6000);
System.out.print("End1 ");
} finally {
lock.unlock();
}
} catch (InterruptedException ex) {
// Interrupted.
}
}
}
static class Thread2 extends Thread {
public void run() {
try {
lock.lockInterruptibly();
try {
System.out.print("Start2 ");
delay(2000);
System.out.print("End2 ");
} finally {
lock.unlock();
}
} catch (InterruptedException ex) {
// Interrupted.
}
}
}
}
Prints:
StartMain Startl EndMain End1
It´s because the JVM kills your threads when the main thread is shutting down.

Categories

Resources