java wait and notify - java

I'm taking one Integer variable and sharing with two threads. One thread should print even numbers and one thread should print odd number sequentially.
But notify() throwing IllegalMonitorStateException.
package mywaitnotifytest;
public class App {
public static void main(String[] args) {
Integer i=0;
Even even = new Even(i);
even.setName("EvenThread");
Odd odd = new Odd(i);
odd.setName("OddThread");
even.start();
odd.start();
}
}
class Even extends Thread{
Integer var;
Even(Integer var){
this.var=var;
}
#Override
public void run() {
while(true){
synchronized (var) {
if(var%2==0){
try {
var.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
var++;
System.out.println(Thread.currentThread().getName()+" "+var);
var.notify();
}
}
}
}
class Odd extends Thread{
Integer var;
Odd(Integer var){
this.var=var;
}
#Override
public void run() {
while(true){
synchronized (var) {
if(var%2!=0){
try {
var.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
var++;
System.out.println(Thread.currentThread().getName()+" "+var);
var.notify();
}
}
}
}
And the output is :
OddThread 1
Exception in thread "OddThread" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at mywaitnotifytest.Odd.run(App.java:67)

I think this is sufficiently different to the usual answer to give another one.
In this case you are using synchronized. When you apply a lock it is on a object not a reference.
synchronized (var) {
This locks the object var references, not on var as a field.
var++;
This replaces the object var points to. It is the same as
var = Integer.valueOf(var.intValue() + 1);
Note: Integer and indeed all the primitive wrappers are Immutable. When you perform any operation on them you are actually unboxing, calculating using the primitive value and re-boxing the object. It is possible to get the same object back if it is pooled. e.g.
Integer i = 10;
i += 0; // gives back the same object.
However, if the object is not pooled
Double d = 10;
d += 0; // creates a new object.
var.notify();
Attempts the call notify on the new object, not the one which was locked.
You shouldn't attempt to lock a field which you mutate. It won't do what it appears to do. You also shouldn't lock on a pooled object. In this case you could have another thread using the same Integer for an unrelated purpose and notify() will wake up an unrelated thread.
To use wait/notify correctly, you should
notify() or notifyAll() after a state change in another shared field.
you should use a while loop for wait() to check the state change.
If you don't do this
notify can be lost if another thread is not waiting.
wait can wake spuriously, even when no notify was called.
For the above requirement what is the edit suggested in the code? How do i share the same object for multiple threads?
public class PingPong implements Runnable {
static class Shared { int num; }
private final Shared var;
private final int bit;
public static void main(String[] args) {
Shared var = new Shared();
new Thread(new PingPong(var, 0), "EvenThread").start();
new Thread(new PingPong(var, 1), "OddThread").start();
}
PingPong(Shared var, int bit) {
this.var = var;
this.bit = bit;
}
#Override
public void run() {
try {
String name = Thread.currentThread().getName();
while (true) {
synchronized (var) {
while (var.num % 2 == bit)
var.wait();
var.num++;
System.out.println(name + " " + var.num);
var.notify();
}
}
} catch (InterruptedException e) {
System.out.println("Interrupted");
}
}
}

Instead of using Integer wrapper class,I created my own class and now It works fine.
package mywaitnotifytest;
public class App {
public static void main(String[] args) {
MyInt i = new MyInt(0);
Even even = new Even(i);
even.setName("EvenThread");
Odd odd = new Odd(i);
odd.setName("OddThread");
even.start();
odd.start();
}
}
class Even extends Thread {
MyInt var;
Even(MyInt var) {
this.var = var;
}
#Override
public void run() {
while (true) {
try {
Thread.sleep(200);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
synchronized (var) {
if (var.i % 2 == 0) {
try {
var.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
var.i++;
System.out.println(Thread.currentThread().getName() + " " + var.i);
var.notify();
}
}
}
}
class Odd extends Thread {
MyInt var;
Odd(MyInt var) {
this.var = var;
}
#Override
public void run() {
while (true) {
try {
Thread.sleep(2000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
synchronized (var) {
if (var.i % 2 != 0) {
try {
var.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
var.i++;
System.out.println(Thread.currentThread().getName() + " " + var.i);
var.notify();
}
}
}
}
class MyInt {
int i = 0;
public MyInt(int i) {
super();
this.i = i;
}
#Override
public String toString() {
// TODO Auto-generated method stub
return "" + i;
}
}

Related

Can static variables ever be used to synchronize threads?

Below I have constructed an example which synchronizes three threads based on a static variable:
public class CallMethodsInOrder {
public static void main(String[] args) {
// Three instances of Thread, first calls first, second second and third third.
// Ensure that they are all called in order.
Thread first = new Thread(new FooRunner(new Foo(),MethodToCall.FIRST));
Thread second = new Thread(new FooRunner(new Foo(),MethodToCall.SECOND));
Thread third = new Thread(new FooRunner(new Foo(),MethodToCall.THIRD));
third.start();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
second.start();
first.start();
}
}
class Foo {
static boolean hasFirstRun = false;
static boolean hasSecondRun = false;
static boolean hasThirdRun = false;
public Foo() {
}
public void first() {
System.out.println("First");
hasFirstRun = true;
}
public void second() {
System.out.println("Second");
hasSecondRun = true;
}
public void third() {
System.out.println("Third");
hasThirdRun = true;
}
}
class FooRunner implements Runnable{
private Foo foo;
private MethodToCall method;
public FooRunner(Foo foo, MethodToCall method) {
this.foo = foo;
this.method = method;
}
#Override
public void run() {
if(method == MethodToCall.FIRST) {
foo.first();
}
else if (method == MethodToCall.SECOND){
while(!Foo.hasFirstRun) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
foo.second();
}
else if (method == MethodToCall.THIRD) {
while(!Foo.hasSecondRun) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
foo.third();
}
}
}
enum MethodToCall{
FIRST, SECOND, THIRD;
}
Is this a valid approach? I have read that static variables are not thread safe, however, cannot see a situation in which the above code would not execute the three methods in the desired order (first, second, third).
Many answers I have found have been related to accessing data structures with multiple threads vs ordering of methods as displayed here.
Since each static variable is only being modified by a single thread is it a problem?
As suggested in the comments, using synchronized is likely the way forward here. I feel the above code still works with static variables however is definitely not the best practise.
A related solution including Semaphores is included below:
public class CallMethodsInOrder2 {
public static void main(String[] args) {
// Three instances of Thread, first calls first, second second and third third.
// Ensure that they are all called in order.
// This approach uses Semaphore vs static variables.
Foo2 foo2 = new Foo2();
Thread first = new Thread(new FooRunner2(foo2,MethodToCall.FIRST));
Thread second = new Thread(new FooRunner2(foo2,MethodToCall.SECOND));
Thread third = new Thread(new FooRunner2(foo2,MethodToCall.THIRD));
third.start();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
second.start();
first.start();
}
}
class Foo2 {
private Semaphore one, two;
public Foo2() {
one = new Semaphore(1);
two = new Semaphore(1);
try {
one.acquire();
two.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void first() {
System.out.println("First");
one.release();
}
public void second() {
try {
one.acquire();
System.out.println("Second");
one.release();
two.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void third() {
try {
two.acquire();
two.release();
System.out.println("Third");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
I think the static variable method 'works' in this case (for some value of 'works'), but is definitely less efficient.
You're sleeping an arbitrary amount of time in each thread ('100'), and then waking up to poll this variable. In the case of a semaphore, the OS takes care of the sleep/wake events to the threads.

IllegalMonitorStateException on notifyAll [duplicate]

I'm new to using wait() and notify() in Java and I'm getting an IllegalMonitorStateException.
Main Code
public class ThreadTest {
private static Integer state = 0;
public static void main(String[] args) {
synchronized(state) {
System.out.println("Starting thread");
Thread t = new Thread(new AnotherTest());
t.start();
synchronized(state) {
state = 0;
while(state == 0) {
try {
state.wait(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("State is: " + state);
}
}
}
public static class AnotherTest implements Runnable {
#Override
public void run() {
synchronized(state) {
state = 1;
state.notify();
}
}
}
}
I'm getting an IllegalMonitorStateException what state.notify() is called. Any ideas?
Edit: Based on answer below here is code that works. As a side note, I was first trying this with an enum which has the same problem of using Integer.
public class ThreadTest {
private static int state = 0;
private static Object monitor = new Object();
public static void main(String[] args) {
synchronized(monitor) {
System.out.println("Starting thread");
Thread t = new Thread(new AnotherTest());
t.start();
state = 0;
while(state == 0) {
try {
for(int i = 0; i < 5; i++) {
System.out.println("Waiting " + (5 - i) + " Seconds");
Thread.sleep(1000);
}
monitor.wait(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("State is: " + state);
}
}
public static class AnotherTest implements Runnable {
#Override
public void run() {
synchronized(monitor) {
state = 1;
monitor.notify();
}
}
}
}
This
private static Integer state = 0;
is equivalent to
private static Integer state = Integer.valueOf(0);
The invocation of valueOf(0) returns a reference to an Integer object, call it A.
You then do
synchronized(state) {
your thread acquires the lock on the object referenced by state, currently that is A.
You then do
state = 1;
which is equivalent to
state = Integer.valueOf(1);
which gives you a different reference to an Integer object, call it B, and assigns it to state. When you then call
state.notify();
you're invoking notify() on an object, B, for which your thread doesn't own the monitor. You can't call notify or wait on objects for which your thread doesn't own the monitor.

Getting illegal monitor state exception on notify

The below program is supposed to print even and odd numbers by two different threads but I am getting illegal monitor exception on notify method in the below code :
public class oddeven {
static volatile Integer t = 0;
public static void main(String as[]) {
oddrunnable or = new oddrunnable(t);
evenrunnable er = new evenrunnable(t);
Thread t1 = new Thread(or, "odd");
Thread t2 = new Thread(er, "even");
t1.start();
t2.start();
}
}
class oddrunnable implements Runnable {
Integer t;
public oddrunnable(Integer t) {
this.t = t;
}
#Override
public void run() {
// TODO Auto-generated method stub
synchronized (t) {
while (true) {
if (t % 2 == 0) {
try {
t.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("Current thread id " + Thread.currentThread().getName());
t++;
t.notify();
}
}
}
}
class evenrunnable implements Runnable {
Integer t;
public evenrunnable(Integer t) {
this.t = t;
}
#Override
public void run() {
// TODO Auto-generated method stub
// TODO Auto-generated method stub
synchronized (t) {
while (true) {
if (t % 2 != 0) {
try {
t.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("Current thread id " + Thread.currentThread().getName());
t++;
t.notify(); // <-------------------exception on this line
}
}
}
}
the notify method is called on the synchronized object itself. Not sure why this is coming :
Current thread id even
Exception in thread "even" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at evenrunnable.run(oddeven.java:86)
at java.lang.Thread.run(Thread.java:619)
Integers in java wrapper are immutable, so as soon as you do t++, you are going to assign a new Integer object which you didn't took lock against and hence you get IllegalMonitorStateException.
Instead of Integer, use AtomicInteger and then use incrementAndGet api to increment the value of counter.
The problem is in using Integer object for synchronization and than doing increment(++) operation on it. I think its creating new integer object and than all the synchronized logic is going for toss. I am not sure about it as while debugging your code, eclipse was not showing whether it created new object.
A better alternative is to use some wrapper object around your integer or AtomicInteger class. Here is your code with AtomicInteger class used
public class oddeven {
static volatile AtomicInteger t = new AtomicInteger(0);
public static void main(String as[]) {
oddrunnable or = new oddrunnable(t);
evenrunnable er = new evenrunnable(t);
Thread t1 = new Thread(or, "odd");
Thread t2 = new Thread(er, "even");
t1.start();
t2.start();
}
}
class oddrunnable implements Runnable {
AtomicInteger t;
public oddrunnable(AtomicInteger t) {
this.t = t;
}
#Override
public void run() {
// TODO Auto-generated method stub
synchronized (t) {
while (true) {
if (t.intValue() % 2 == 0) {
try {
t.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("Current thread id " + Thread.currentThread().getName());
t.incrementAndGet();
t.notify();
}
}
}
}
class evenrunnable implements Runnable {
AtomicInteger t;
public evenrunnable(AtomicInteger t) {
this.t = t;
}
#Override
public void run() {
// TODO Auto-generated method stub
// TODO Auto-generated method stub
synchronized (t) {
while (true) {
if (t.intValue() % 2 != 0) {
try {
t.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("Current thread id " + Thread.currentThread().getName());
t.incrementAndGet();
t.notify(); // <-------------------exception on this line
}
}
}
}

Print odd and even using two threads in Java

I am trying to do it using two threads like below. Can someone point the obvious mistake I am doing here?
public class OddEven {
public static boolean available = false;
public static Queue<Integer> queue = new LinkedList<Integer>();
static Thread threadEven = new Thread() {
#Override
public void run() {
printEven();
}
public synchronized void printEven() {
while (!available) {
try {
wait();
Thread.sleep(2000);
} catch (InterruptedException e) {
}
}
System.out.println(queue.remove());
available = false;
notifyAll();
}
};
static Thread threadOdd = new Thread() {
#Override
public void run() {
printOdd();
}
public synchronized void printOdd () {
while (available) {
try {
wait();
Thread.sleep(2000);
} catch (InterruptedException e) {
}
}
System.out.println(queue.remove());
available = true;
notifyAll();
}
};
public static void main(String[] args) {
int n = 20;
for (int i = 1; i < n; i++) {
queue.add(i);
}
threadOdd.start();
threadEven.start();
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
threadOdd.join();
threadEven.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
But this program is only printing 1 and quitting. After printing 1 the available should be true and printEven should wake up, print and set available to false. I don't understand what is going wrong here? I saw other solutions but want to know why my solution is not working.
Putting synchronized on an instance method means that the thread calling that method has to acquire the lock on that instance; public void synchronized printOdd() is syntax sugar for
public void printOdd() {
synchronized(this) {
...
}
}
where this is different for each instance, since ThreadOdd and threadEven are two different objects and each one uses its own lock. The methods notifyAll and wait are called on the object that is being used as the lock. When one thread waits it never gets notified because the notification only applies to other threads waiting on the same lock as the notifying thread.

Java - multithreading and synchronization

I have two very similar programs each trying to run two threads OddThread and EvenThread and trying to print the odd and even numbers in sequence . While the first one works , the second one hangs . Can anyone please pinpoint the bug in the second program ?
The first one which works :
public class ThreadTest {
public static void main(String[] args) {
System.out.println("Odd Even test");
NumHolder objNumHolder = new NumHolder();
Odd o1 = new Odd(objNumHolder, "Odd Number Thread");
Even e1 = new Even(objNumHolder, "Even Number Thread");
o1.start();
e1.start();
}
}
class NumHolder {
private int intCurrNum;
private boolean isEven = false;
public synchronized void printOddNumber(String tname) {
while (isEven == true){
try {
wait();
}catch (InterruptedException e) {
}
}
isEven = true;
System.out.println("Thread Name="+tname + "===Number="+intCurrNum);
intCurrNum += 1;
notifyAll();
}
public synchronized void printEvenNumber(String tname) {
while (isEven == false) {
try {
wait();
} catch (InterruptedException e) {
}
}
isEven = false;
System.out.println("Thread Name="+tname + "===Number="+intCurrNum);
intCurrNum += 1;
notifyAll();
}
}
class Even extends Thread {
private NumHolder objNumHolder;
public Even(NumHolder p_objNumHolder, String name) {
super(name);
objNumHolder=p_objNumHolder;
}
public void run() {
for (int i = 0; i < 10; i++) {
objNumHolder.printEvenNumber(getName());
}
}
}
class Odd extends Thread {
private NumHolder objNumHolder;
public Odd(NumHolder p_objNumHolder,String name) {
super(name);
objNumHolder = p_objNumHolder;
}
public void run() {
for (int i = 0; i < 10; i++) {
objNumHolder.printOddNumber(getName());
}
}
}
The second code which hangs :
class PrintClass {
int intCurrNum;
private boolean isEven = false;
synchronized void printOdd(){
while(isEven){
try{
wait();
}catch(InterruptedException ie){
System.out.println("Interrupted exception in printOdd()");
ie.printStackTrace();
}
isEven = true;
System.out.println("Thread Name="+Thread.currentThread().getName() + "===Number="+intCurrNum);
intCurrNum += 1;
notifyAll();
}
}
synchronized void printEven(){
while(!isEven){
try{
wait();
}catch(InterruptedException ie){
System.out.println("Interrupted exception in printEven()");
ie.printStackTrace();
}
isEven = false;
System.out.println("Thread Name="+Thread.currentThread().getName() + "===Number="+intCurrNum);
intCurrNum += 1;
notifyAll();
}
}
}
class ThreadOdd extends Thread {
PrintClass pc = null;
ThreadOdd(PrintClass pc , String name){
super(name);
this.pc = pc;
}
public void run(){
for (int i = 0; i < 10; i++) {
pc.printOdd();
}
}
}
class ThreadEven extends Thread {
PrintClass pc = null;
ThreadEven(PrintClass pc,String name){
super(name);
this.pc = pc;
}
public void run(){
for (int i = 0; i < 10; i++) {
pc.printEven();
}
}
}
public class EvenOddPrintClass {
public static void main(String[] args){
PrintClass pc = new PrintClass();
Thread to = new ThreadOdd(pc,"ThreadOdd");
Thread te = new ThreadEven(pc,"ThreadEven");
to.start();
te.start();
}
}
Thanks.
I suggest you run your code in the debugger and step through both threads. It's very educational. You will see exactly where the error is.
In both versions, isEven starts out as false.
In the first version, printOddNumber will skip the whole while loop, print the odd number, set isEven to true and notify the even thread, which will print the even number and notify the odd thread again etc. in sequence.
In the second version, printOddNumber will skip the whole while loop, including printing the number and notifying the even thread. After 10 attempts it will exit without having printed anything, and leaving the even thread hanging without ever having notified it.
Interesting. So initially the isEven = false. If the printOdd() is called first then the while (isEven) test is false so printOdd() will exit immediately without generating any output. The while loops in your first program only encompass the wait test, not the entire method.
Then when printEven() is called by the other thread, it will call wait() and hang since there is no other thread to call notifyAll().
You only should want the while loop around the wait since you are going to exit after you print out the even or odd number anyway, right? So the logic in the first program is correct.
public class CountDownApp
{
public static void main(String[] args)
{
Thread count1 = new CountDownEven();
Thread count2 = new CountDownOdd();
count1.start();
count2.start();
}
}
class CountDownEven extends Thread
{
public void run()
{
for(int i=10;i>0;i-=2)
{
System.out.print(+i+"-");
try {
Thread.sleep(2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class CountDownOdd extends Thread
{
public void run()
{
for(int i=9;i>0;i-=2)
{
System.out.print(+i+"-");
try {
Thread.sleep(2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

Categories

Resources