Two threads referring one variable

I am running the below class .

public class RunThreads implements Runnable {
    static int  i;
    public static void main(String[] args) {
        RunThreads job = new RunThreads();
        Thread alpha = new Thread(job);
        Thread beta = new Thread(job);
        alpha.setName("Alpha");
        beta.setName("beta");
        alpha.start();
        beta.start();
    }
    public void run(){
        for(;i<10;i++){
            System.out.println(Thread.currentThread().getName() + i);
        }
    }
}

And my output is :

beta0
beta1
Alpha0
beta2
beta4
beta5
beta6
Alpha3
Alpha8
beta7
Alpha9

I understand I will get different outputs every time I execute it. My question is, why does the output have the value of i as 0 twice, for both the alpha and beta threads i.e. Alpha0 and beta0.

The value of i has been incremented to 1 by the beta thread. So, how does the alpha thread print out Alpha0

I maybe missing something very obvious here. Thanks !

Jon Skeet
people
quotationmark

Things are scary when you access shared data with no synchronization etc:

  • There's no guarantee that the Alpha thread reading i will see the "latest" update from the beta thread or vice versa
  • It's possible for both threads to start i++ at roughly the same time... and as i++ is basically:

    int tmp = i;
    tmp++;
    i = tmp;
    

    you can easily "lose" increments

If you want to make this thread-safe, you should use AtomicInteger instead:

import java.util.concurrent.atomic.AtomicInteger;

public class RunThreads implements Runnable {
    static AtomicInteger counter = new AtomicInteger();
    public static void main(String[] args) {
        RunThreads job = new RunThreads();
        Thread alpha = new Thread(job);
        Thread beta = new Thread(job);
        alpha.setName("Alpha");
        beta.setName("beta");
        alpha.start();
        beta.start();
    }
    public void run(){
        int local;
        while ((local = counter.getAndIncrement()) < 10) {
            System.out.println(Thread.currentThread().getName() + local);
        }
    }
}

Your output may still appear to be in the wrong order (because the alpha thread may "start" writing "Alpha0" while the beta thread "starts" writing "beta1" but the beta thread gets the lock on console output first), but you'll only see each count once. Note that you have to use the result of getAndIncrement() for both the checking and the printing - if you called counter.get() in the body of the loop, you could still see duplicates due to the interleaving of operations.

people

See more on this question at Stackoverflow