0

My code is given below.

In the for loop I am getting unexpected output i.e.
before completing the execution of for loop by 1st thread the 2nd thread comes in for loop and shows incremented value.

public class ThreadSafe {
    public static void main(String[] args) throws InterruptedException {
        System.out.println("main()");

        B b=new B("1st Thread");
        B b1=new B("2nd Thread");
        B b2=new B("3rd Thread");
        b.start();
        b1.start();
        b2.start();
    }
}

class MyCounter {
    private static int count;

    public static int getCount(){
        for(int m=0;m<2;m++){
            System.out.println(count+" "+Thread.currentThread().getName());
        }

        return count++;
    }         
}

class B extends Thread{
    public B(String tname) {
        super(tname);
    }

public void run() {
    MyCounter.getCount();
    }
}

The question is when 1st thread executes for loop then other threads executing return statement is this the reason of showing increment value or something else?

How other thread can show the incremented value unless the 1st thread reaches the return statement?

1

first 2 points to make:

  1. there is not guarantee that the thread's execution will be interleaved, short pieces of code will likely complete uninterrupted. Add sleeps if you want to lessen this effect.

  2. count++ is not thread safe, it expands to int tmp=count; count=tmp+1; and the thread may be interrupted between the tmp=count and count=tmp+1. Instead use an AtomicInt and incrementAndGet.

The increment of the static count may not be visible to the other thread, it takes a while before changes to a variable become visible to other threads. Using a volatile field will lessen that but you will still see points 1 and 2 in effect.

Also print statements are buffered before being written out so the order of the print statements don't necessarily mean that they were called in that order.

11
  • i agree sir, but question is that which thread is executing count++.Because count++ is outside the loop as a return stmt. so if first thread is executing first cycle of for loop before reaching to count++ then in second cycle of loop for first thread showing incremented value.How?? – Avi May 15 '14 at 13:10
  • @avi the first thread reached the end of it's timeslice between cycles and another thread incremented count – ratchet freak May 15 '14 at 13:11
  • didn't understand... – Avi May 15 '14 at 13:23
  • @avi why don't you add the output you get to the question instead of trying to explain it – ratchet freak May 15 '14 at 13:24
  • o/p are varying. when i run this prog first time then i get like this- main() 0 2nd Thread 0 2nd Thread 0 1st Thread 1 1st Thread 0 3rd Thread 2 3rd Thread – Avi May 15 '14 at 13:32
0

Example output:

0 1st Thread
1 3rd Thread
1 3rd Thread
2 1st Thread
0 2nd Thread
0 2nd Thread

What you're seeing here is that your threads have locally cached your count variable, as it is not declared as being volatile:

When applied to a field, the Java volatile guarantees that:

(In all versions of Java) There is a global ordering on the reads and writes to a volatile variable. This implies that every thread accessing a volatile field will read its current value before continuing, instead of (potentially) using a cached value.

(emphasis mine)

Being volatile won't save your counter from misbehaving under ++ though, as it is not an atomic operation:

[That] an increment expression, such as counter++, does not describe an atomic action. Even very simple expressions can define complex actions that can decompose into other actions[...] Atomic actions cannot be interleaved, so they can be used without fear of thread interference.

The Java tutorial on concurrency is a great place to learn about these things.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.