0

I have the following question: why in this case the second thread see when the first thread changes the value of number:

public static void main(String[] args) throws InterruptedException {

    Temp t = new Temp();
    t.go();
}

static class Temp {
    int number = 2;

    public void go() {

        new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                number = 100;
            }
        }).start();

        new Thread(new Runnable() {

            @Override
            public void run() {
                while (true) {
                    System.out.println(number);
                }
            }
        }).start();
    }
}

I expected number value to be cached from the second thread and when the first thread change it, the second thread will be "uninformed" for that and it will print always 2 ! But in practice when the first thread changed the number variable the second thread see this change and start printing 100. Why is that ? I know that it is not 100% sure that the second thread will cache the variable, but in most cases it does this. I thing that I am missing somethig important. Thanks in advance.

4
  • 2
    Both threads access the number-variable on object-level. There is no such caching as you think of. I would be curious why it should be different as here. This inter-thread communication model is called Shared-Memory. Commented Jun 23, 2015 at 12:47
  • firstly you can not declare a class as static!! Commented Jun 23, 2015 at 12:49
  • As already stated the variable is part of the Temp instance that is used to create both threads and thus both threads have access to that very same instance and its data. Commented Jun 23, 2015 at 12:50
  • 2
    @Hiru you can if it's an inner class as is the case here. In that case static means that the outer class is merely a namespace, i.e. the normal "special relation" between inner and outer doesn't exist. Commented Jun 23, 2015 at 12:50

2 Answers 2

8

According to the Java Memory Model it's not guaranteed that the value changed by one thread will be visible from another. However it does not say the opposite: it can be visible. It's up to the implementation of virtual machine and your hardware. If it's visible today on your CPU with your VM it does not mean that it will be visible always on every hardware and every virtual machine. You just cannot rely on this.

If you still want to see the effect, you can replace the second thread code with the following one:

new Thread(new Runnable() {

    @Override
    public void run() {
        while (number < 100) {
        }
        System.out.println(number);
    }
}).start();

This produces stable result on HotSpot virtual machine: your program never ends (though adding a volatile keyword on number field will make it ending in 5 seconds). Of course you cannot rely on this either.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. Did you try this ? And the cycle is infinite?
Can you give a link to the relevant documentation part, please.
0

This is what is known as "shared memory".

The variable "number" is in memory shared by both threads (heap), not on each thread stack.

That's why changing it in one thread reflects on the other.

1 Comment

And when we can have this "invisibility" and why? Can you give little example with explanation ? Thanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.