Integer value not getting refreshed

ashish2199 :

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.

Jon Skeet :

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.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=90606&siteId=1