I am trying to print even and odd using two separate threads which communicate with each other by wait and notify.
I do know that i refers to Integer object which is in heap. hence changes made by one thread should be visible to both thread. Also I am using volatile keyword for declaration of Integet i.
I cant seem to understand how value of variable i is shown as 1 even after it has been incremented.
The output of code is
Even Thread got lock i=1
Even Thread waiting.. i=1
Odd Thread got lock i=1
Odd Thread : i=2
Odd Thread Run called NotifyAll
Odd Thread got lock i=2
Odd Thread waiting.. i=2
Even Thread woken up.. i=1
Even Thread waiting.. i=1
package programs;
public class EvenOdd {
static Object lck = new Object();
volatile static Integer i=1;
volatile static Integer N = 1000;
public static void main(String args[]){
EvenRunner e = new EvenRunner(lck, i, N);
OddRunner o = new OddRunner(lck, i, N);
Thread t1 = new Thread(e,"Even Thread ");
Thread t2 = new Thread(o,"Odd Thread ");
t1.start();
t2.start();
try {
t1.join();
t2.join();
}catch(InterruptedException ex) {
System.out.println("Interrupted : "+ex);
}
}
}
class EvenRunner implements Runnable{
Object lck;
Integer i;
Integer N;
EvenRunner(Object lck,Integer i,Integer N){
this.lck=lck;
this.i=i;
this.N=N;
}
@Override
public void run() {
while(i<N) {
synchronized(lck) {
System.out.println(" Even Thread got lock i="+i);
while(i%2==1){
try {
System.out.println(" Even Thread waiting.. i="+i);
lck.wait();
System.out.println(" Even Thread woken up.. i="+i);
}catch(InterruptedException e) {
System.out.println("Interrupted thread : "+e);
}
}
++i;
System.out.println(Thread.currentThread().getName()+" : i="+i);
System.out.println(" Even Thread Run called NotifyAll");
lck.notifyAll();
}
}
}
}
class OddRunner implements Runnable{
Object lck;
Integer i;
Integer N;
OddRunner(Object lck,Integer i,Integer N){
this.lck=lck;
this.i=i;
this.N=N;
}
@Override
public void run() {
while(i<N) {
synchronized(lck) {
System.out.println(" Odd Thread got lock i="+i);
while(i%2==0){
try {
System.out.println(" Odd Thread waiting.. i="+i);
lck.wait();
System.out.println(" Odd Thread woken up.. i="+i);
}catch(InterruptedException e) {
System.out.println("Interrupted thread : "+e);
}
}
++i;
System.out.println(Thread.currentThread().getName()+" : i="+i);
System.out.println(" Odd Thread Run called NotifyAll");
lck.notifyAll();
}
}
}
}
Expected Result: should be that other thread should also see the value of variable I as 2 after it has been incremented.
Actual result: value of variable i is read as 1 by other thread even after incrementing it.
Expected output should be that other thread should also see the value of variable I as 2 after it has been incremented.
When you construct evenRunner
and oddRunner
, you're copying the same Integer
reference into each class as an instance field.
But Integer
is immutable - when you execute ++i;
that changes the field to refer to a different Integer
object. It doesn't modify the content of the existing integer object... so your two threads are operating on entirely separate fields, and won't interact at all.
If you want to have a single object that both threads can modify, use AtomicInteger
instead.