Print odd & even number using Multi threading [duplicate] - java

This question already has answers here:
IllegalMonitorStateException on wait() call
(12 answers)
Closed 5 years ago.
I am trying to learn Multi threading and for practice, I am trying to print odd & even number using two thread. I have created an object which will act as a lock for the both the threads. When I try to execute it throws java.lang.IllegalMonitorStateException.
class EVENODDimpl implements Runnable {
int num;
int temp = 0;
Object lock = new Object();
public EVENODDimpl( int num) {
this.num = num;
}
public void run() {
try {
synchronized (lock) {
while(temp<num) {
temp++;
System.out.println(Thread.currentThread().getName()+" "+temp);
this.notify();
this.wait();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Main Method:
public class EVENODD {
public static void main(String[] args) {
int i = 10;
EVENODDimpl ei = new EVENODDimpl(i);
Thread t1 = new Thread( ei,"EvenThread");
Thread t2 = new Thread( ei,"OddThread");
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

You wait and notify on this, but you should wait and notify on lock because you synchronize on lock, you can't wait and notify on other object than the one on which you're synchronizing, working version:
class EVENODDimpl implements Runnable {
int num;
int temp = 0;
Object lock = new Object();
public EVENODDimpl( int num) {
this.num = num;
}
public void run() {
try {
synchronized (lock) {
while(temp<num) {
temp++;
System.out.println(Thread.currentThread().getName()+" "+temp);
lock.notify();
lock.wait();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

As it said from the javadoc
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.
This means that your methods notify and wait should own monitor. Or in other words the object that is calling these method must be synchronized. Your this object is not synchronized. That's why you get this exception. Call this method from lock object in your case.
Your logic is still wrong but it is up to you to explore that.

java.lang.IllegalMonitorStateException Exception occur because you are using notify method on the object this.notify() but that Object is not synchronized.
Replace synchronized (lock) with this: synchronized (this)

Related

Threads stopped print characters and all of them are waiting for lock

I want to use 3 threads to print A、B、C randomly,so I wrote code as below:
public class ThreadPrint4Test {
public static void main(String[] args) {
new ThreadPrint4Test().testPrint();
}
public void testPrint() {
Object lock = new Object();
new Thread(new PrintThread("A",lock),"thread-A").start();
new Thread(new PrintThread("B",lock),"thread-B").start();
new Thread(new PrintThread("C",lock),"thread-C").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
new Thread(() -> {
synchronized (lock) {
lock.notifyAll();
}
}).start();
}
class PrintThread implements Runnable {
private Object lock;
private String value;
public PrintThread(String value, Object lock) {
this.value = value;
this.lock = lock;
}
public void run() {
while (true) {
try {
synchronized (lock) {
lock.wait();
System.out.println(LocalTime.now() + "\t" + value);
lock.notifyAll();
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
}
But when I test the program,it stoppted print characters after a few seconds
Using jps and jstack I found all the 3 threads are WAITING the object lock
I tested it for serveral times,and this phenomenon occurs every time.
I do not know why all the 3 threads are waiting object lock at same time
Based on my knowledge,each time one of the 3 threads will be awake and have the chance to exeute,then it will awake all the 3 threads randomly by invoking lock.notifyAll();. So the program should run continuous theoretically,But now each time I test it,it will stop print characters after a few seconds.
Could someone help analysis why this happen? Thanks in advance!
while (true) {
try {
synchronized (lock) {
lock.wait();
System.out.println(LocalTime.now() + "\t" + value);
lock.notifyAll();
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
Your problem is that you are calling notifyAll() immediately after calling wait(). You get to a deadlock situation where each thread is waiting. When all the threads are waiting, none of them can be notified, hence your program comes to a standstill.
According to the Concurrency tutorial, you need to wait() for a certain condition to occur. Once the condition occurs, you perform the required action (which, in your code, is printing the current time) then you call notifyAll() to inform the waiting threads that you have completed performing the required action and that they can try to perform their required action.
Explanations after the code.
import java.time.LocalTime;
public class ThreadPrint4Test {
private volatile boolean canPrint;
public void testPrint() {
Object lock = new Object();
new Thread(new PrintThread("A", lock), "thread-A").start();
new Thread(new PrintThread("B", lock), "thread-B").start();
new Thread(new PrintThread("C", lock), "thread-C").start();
}
class PrintThread implements Runnable {
private Object lock;
private String value;
public PrintThread(String value, Object lock) {
this.value = value;
this.lock = lock;
canPrint = true;
}
public void run() {
while (true) {
while (!canPrint) {
try {
synchronized (lock) {
System.out.printf("[%s] Waiting...%n", value);
lock.wait();
}
}
catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
synchronized (lock) {
canPrint = false;
System.out.println(LocalTime.now() + "\t" + value);
canPrint = true;
lock.notifyAll();
}
}
}
}
public static void main(String[] args) {
new ThreadPrint4Test().testPrint();
try {
Thread.sleep(2000);
}
catch (InterruptedException x) {
x.printStackTrace();
}
System.exit(0);
}
}
I added a canPrint flag. When it is true, then the thread can print the current time. When it is false, the thread must wait.
When the thread can print the current time, it first sets the flag to false so that no other thread can print.
After the thread has printed the current time, it sets the flag back to true and calls method notifyAll() which causes all waiting threads to stop waiting and re-check the canPrint flag.
The first thread to awake after canPrint has been set to true, sets the flag to false which causes all other threads to wait.

Possibility of deadlock with two locks?

Can this code deadlock with thread 1 calling one and thread 2 calling two. That is, can the acquisition of the inner lock be reordered to before the acquisition of the outer one (from the POV of the other thread)?
private final Object foo = new Object();
synchronized void one() {
// ...
synchronized(this.foo) {
// ...
}
// ...
}
synchronized void two() {
// ...
synchronized(this.foo) {
// ...
}
// ...
}
No, this will not deadlock.
When synchronized methods are called the intrinsic lock of this is locked before the method’s body is executed. Here either thread 1 or thread 2 will get to run its method, and the other one will not be able to lock on the intrinsic lock of this.foo so the owner of the lock of this will be able to lock this.foo.
So for with a Simple Test :
class LockTest implements Runnable {
public final Object foo = new Object();
boolean runOne;
public LockTest(boolean runOne) {
this.runOne = runOne;
}
synchronized void one() {
System.out.println("runnin one function");
synchronized(this.foo) {
try {
System.out.println("Enter Sleep function one");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
synchronized void two() {
System.out.println("running two function");
synchronized(this.foo) {
try {
System.out.println("enter sleep function two");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
#Override
public void run() {
if(runOne)
one();
else
two();
}
}
With this in a Main class :
while (true)
{
LockTest document2 = new LockTest(true);
LockTest document3 = new LockTest(false);
Thread tread1 = new Thread(document2);
Thread tread2 = new Thread(document3);
tread1.start();
tread2.start();
a++;
if(a==10)
break;
}
We are not locking and even watching with a Thread Dump everything is working Fine. Why? Because every time we are initializating a new Thread with a new object foo. But if that object is declared as static it will be a lock and the others threads need to wait. So from my test and POV. No, it can't be deadlocked.

Java Thread Class : java.lang.IllegalMonitorStateException

This is my first post so sorry if I do something wrong.
I'm trying to understand how work the threads in Java, in particular the synchronization, that's why I created a little piece of code which is supposed to print 1, 2, 3, 4, 5, 6 (in one thread) and then a second thread wait that's the first finished and then print 6, 5, 4, 3, 2, 1 but it only do the first 6 steps and tell me that there is a monitor problem for the wait method in the thread t2 and a problem with the notify all of the thread t1. Maybe I haven't understood anything about the synchronization of an object. Here is my code :
public class anObject extends Thread {
long value;
String name;
public anObject(long value, String name) {
this.value = value;
this.name = name;
}
public synchronized void add() {
this.value++;
}
public synchronized void sub() {
this.value--;
}
public static void main(String[] args) {
anObject il = new anObject(0, "Bob");
synchronized (il) {
Thread t1 = new Thread(il) {
public void run() {
while (il.value > 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int i = 0; i < 6; i++) {
il.add();
System.out.println(il.value);
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
il.notifyAll();
}
};
Thread t2 = new Thread(il) {
public void run() {
while (il.value < 6) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int j = 0; j < 6; j++) {
il.sub();
System.out.println(il.value);
try {
sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
il.notifyAll();
}
};
t1.start();
t2.start();
}
}
}
And this is what appeared in the terminal :
Exception in thread "Thread-2" 1
java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Unknown Source)
at anObject$2.run(anObject.java:53)
2
3
4
5
6
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
at anObject$1.run(anObject.java:45)
Thanks a lot for your help!
Greetings
wait is defined in Object, this is why you get this exceptions.
I prefer dedicated lock for avoid the unpredictable monitor exceptions:
private final Object lock = new Object();
private static final class Lock { }
private final Object lock = new Lock();
For notify or notifyAll an object, you need to be holding the lock with the synchronized statement. Also, you should define a loop to check for the wakeup condition.
synchronized (lock) {
while (!isWakeupNeeded()) {
lock.wait();
}
}
To notify:
synchronized (lock) {
makeWakeupNeeded();
lock.notifyAll();
}
What you are doing by this
synchronized (il)
is just grabbing an object's monitor from the main thread. But inside you are initializing two new threads and trying to call the wait() method from the contexts of both of these recently initialized and then started threads. The main idea of IllegalMonitorStateException is that you are trying to call a method that uses a context of object's locking without preceding obtaining of this object's lock. What you can do to fix it fast is just to change
while (il.value > 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
on
while (il.value > 0) {
try {
synchronized(this) {
this.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
and to make an equal change in the second block of code. But to really make it right, I would recommend you to turn to some strong sources describing multithreading concept. Oracle's basic java tutorial will be just fine I suppose.

Indefinite thread waiting in Java

I am trying to generate Odd/Even numbers using 2 threads using wait notify.
But It is just printing 1.
Below is the code:
Even.java
public class Even implements Runnable {
private int i; private Object ob
public Even(int i,Object o) {
this.i=i;
this.ob=o;
}
#Override
public void run() {
while (true) {
synchronized (ob) {
while (i % 2 == 0) {
try {
ob.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
i++;
System.out.println(i);
ob.notifyAll();
}
}
}
}
Odd.java
public class Odd implements Runnable {
private int i; private Object ob;
public Odd(int i) {
this.i=i;
this.ob=o;
}
#Override
public void run() {
while (true) {
synchronized (ob) {
while (i % 2 == 1) {
try {
ob.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
i++;
System.out.println(i);
ob.notifyAll();
}
}
}
}
Test.java
public class Test {
public static void main(String[] args) {
int i = 0;
Object lock = new Object();
Thread t1 = new Thread(new Even(i),lock);
Thread t2 = new Thread(new Odd(i),lock);
t1.start();
t2.start();
}
}
Output:
1
Can anyone tell me where I am making the mistake?
Hmm, I would assume that it could be a problem that Integer appears to be immutable in Java. Thus you will not synchronize on the same objects anymore, if one of the two classes changed the i value (which it apparently does since the first output is 1).
So since you change the value stored in i in Odd and call notifyAll on the new object I that Java will complain since you call notifyAll on an object that actually never has been locked.
The threads have fallen into INDEFINITE WAITING state. Note that (t1 i.e instance of Even and t2 i.e instance of Odd), each have a separate copy of instance variable i.
Here is whats going on behind the scenes:
Initially, both thread t1 (Even) and t2 (Odd) are in READY and then RUNNABLE state
Lets assume t1 is scheduled and gets processor to execute. t1 enters RUNNING state. t1's run() is invoked
while(true) succeeds and control enters outer while loop
because of synchronized(ob) t1 locks object ob
since i is 0 initially; i % 2 == 0 condition evaluates to true
control now enters body of inner while loop, then try block and invokes ob.wait();
t1 enters WAITING state and waits until someone notifies on object ob
Now, t2 is scheduled and gets processor to execute. t2 enters RUNNING state
while(true) succeeds and control enters outer while loop
because of synchronized(ob) t2 locks object ob
i is 0 initially (remember the i incremented previously was local to t1 - Even.i). The variable i in this context is local to t2 i.e. Odd.i.
Hence i % 2 == 1 evaluates to false and control skips inner while loop
Control reaches i++; i is incremented from 0 to 1
The statement System.out.println(i); prints 1 to console
contorl moves to next line and ob.notifyAll(); is invoked and all the threads waiting on object ob (t1 in our case) are notified
At this point, both t1 and t2 are back in RUNNABLE state again
Depends on processor which thread to schedule
Lets assume t1 is scheduled and gets processor to execute
t1 resumes its operations from where it left previously (i.e the statement after ob.wait();)
control reaches catch (InterruptedException e) and since there is no exception, its skipped and control comes back to while ( i % 2 == 0) check
Remember, t1's i (i.e Even.i) is still 0 because control din't reach the line i++; in Even class
Hence i % 2 == 0 evaluates to true and control enters into body of while loop, then enters the try block and invokes ob.wait();
t1 enters WAITING state again and waits until someone notifies on object ob
Now, t2 is scheduled and gets processor to execute. t2 enters RUNNING state
t2 resumes its operations from where it left previously (i.e the statement after ob.notifyAll();)
since there is no other statement after ob.notifyAll();, the control reaches outer while loop
while(true) is evaluated and control enters body of outer while loop
because of synchronized(ob) t1 locks object ob
Remember t2's i is now 1 because it was incremented previously and printed on console
Hence, while ( i % 2 == 1) is evaluated to true and control enters body of inner while loop, then try block and invokes ob.wait();
As a result, t2 enters WAITING state
t1 and t2 are both in WAITING state now; waiting on object ob. Waiting for someone to notify them on object ob. Sadly, there is no one to rescue
Hence the INDEFINITE WAITING
Following code should help in what you are trying to achieve
public class EvenOddTest {
public static void main(String[] args) {
Lock lock = new Lock();
Thread t1 = new Thread(new Even(lock));
Thread t2 = new Thread(new Odd(lock));
t1.start();
t2.start();
}
}
class Lock {
private int data;
public void increment() {
data++;
}
public int getData() {
return data;
}
}
class Even implements Runnable {
private Lock ob;
public Even(Lock o) {
this.ob = o;
}
#Override
public void run() {
while (true) {
synchronized (ob) {
while (ob.getData() % 2 == 0) {
try {
ob.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
ob.increment();
System.out.println(ob.getData());
ob.notifyAll();
}
}
}
}
class Odd implements Runnable {
private Lock ob;
public Odd(Lock o) {
this.ob = o;
}
#Override
public void run() {
while (true) {
synchronized (ob) {
while (ob.getData() % 2 == 1) {
try {
ob.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
ob.increment();
System.out.println(ob.getData());
ob.notifyAll();
}
}
}
}
Note:
I have refactored your code so that the object on which threads try to obtain lock and wait upon, holds the data as well.
lock object is now the shared instance between Even and Odd threads.
With my previous reasoning, the code should be self explanatory.
This is not actual way of doing things in parallel computing, to leverage multi-threading power/capabilities. However, it should be a good starter exercise.
You can put i variable as a class attribute in Test class, then create an object of type Test and pass it as parameter to the constructors:
public class Test {
public Integer i = 0;
public static void main(String[] args) {
Object o = new Object();
Test t = new Test();
Thread t1 = new Thread(new Even(t,o));
Thread t2 = new Thread(new Odd(t,o));
t1.start();
t2.start();
}
}
public class Even implements Runnable {
private Test t;
private Object o;
public Even(Test t, Object o) {
this.t=t;
this.o=o;
}
#Override
public void run() {
while (true) {
synchronized (o) {
while (t.i % 2 == 0) {
try {
o.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
t.i++;
System.out.println(t.i);
o.notifyAll();
}
}
}
}
public class Odd implements Runnable {
private Test t;
private Object o;
public Odd(Test t, Object o) {
this.t=t;
this.o = o;
}
#Override
public void run() {
while (true) {
synchronized (o) {
while (t.i % 2 == 1) {
try {
o.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
t.i++;
System.out.println(t.i);
o.notifyAll();
}
}
}
}

Explain third party static lock behaviour used in synchronization in java

public class ObjectLevelLock implements Runnable{
int count = 0;
int uncount = 10;
public static Object lock = new Object();
public static Object lock1 = new Object();
public void counter(){
synchronized (lock) {
for(int i = 0; i<10; i++){
System.out.println(Thread.currentThread().getName()+"------"+count++);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// decrem();
}
}
}
public void decrem(){
synchronized(lock1){
for(int i =10; i>0; i-- ){
System.out.println(Thread.currentThread().getName()+"------"+uncount--);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public void xxx(){
while(true){
decrem();
counter();
}
}
public void run(){
xxx();
}
public static void main(String[] args) {
ObjectLevelLock obj1 = new ObjectLevelLock();
ObjectLevelLock obj2 = new ObjectLevelLock();
Thread t1 = new Thread(obj1,"Thread 1");
Thread t2 = new Thread(obj2,"Thread 2");
t1.start();
t2.start();
}
}
On executing this program ,I get the following output at some point :
Thread 1------0
Thread 2------0
Thread 1-------1
Thread 2------1
Thread 1-------2
Thread 2------2
Thread 1-------3
Thread 2------3
Thread 1-------4
Thread 2------4
Thread 1-------5
Thread 2------5
Thread 2------6
Thread 1-------6
Thread 2------7
Thread 1-------7
Thread 1-------8
Thread 2------8
Thread 1-------9
As can be seen from output ,both threads are accessing the same method that's why both are incrementing count variable .Please let me know how is that possible ,if I am using static third party locks like
public static Object lock = new Object();
static means lock is acquired on the class which means is should be accessible by only one thread at a time.But then why then output trace showing both threads are in the same method and executing it concurrently.
Output should be :
One thread incrementing count variable other thread should be decrementing uncount variable and these two operation can also happen concurrently

Categories