4

Consider the snippet taken from the book Java Concurrency in Practice by Joshua Bloch-

public class NoVisibility{
    private static boolean ready;
    private static int number;

    private static class ReaderThread extends Thread{
        public void run(){
            while(!ready)
                Thread.yield();
            System.out.println(number);
        }
    }

    public static void main(String[] args){
        new ReaderThread().start();
        number = 42;                            // Statement 1
        ready = true;                           // Statement 2
    }
}

For the main thread started by JVM, is it guaranteed that statement 1 is going to be executed before statement 2.

I perfectly understand that the ReaderThread might not be able to see the updated value of above two static variables. I am not asking for the solution. But if the statement 1 was executed before statement 2, is it still possible for the ReaderThread to see the updated value for ready & not for number? Is this what reordering means in general?


A paragraph at the bottom of the page in the same book reveals an insight into this-

There is no guarantee that operations in one thread will be performed in the order given by the program, as long as the reordering is not detectable from within that thread—even if the reordering is apparent to other threads.

A little confusion here-

The author is saying ... as long as the reordering is not detectable from within that thread... while at the same time, he says-

—even if the reordering is apparent(clearly visible) to other threads.

If in case, the reordering is clearly visible to other threads, why is he saying at the same time "as long as the reordering is not detectable from within that thread"? If the reordering is visible, that means it is detectable also. Isn't it?

Farhan stands with Palestine
  • 13,890
  • 13
  • 58
  • 105
  • *"Yes"* the statements are executed in your written order and for your second question : http://stackoverflow.com/a/16629365/351861 – specializt Aug 01 '16 at 08:32
  • 1
    You can find a good example [here](http://jeremymanson.blogspot.de/2007/08/atomicity-visibility-and-ordering.html). So yes, it is possible. – markus_ Aug 01 '16 at 08:41
  • 1
    "not detectable within that thread" means that *with the current code* it's not detectable. e.g. something like `foo = 1; sleep_ten_minutes(); foo = 2;` may just set foo = 2 from the start because it's not detectable in the executing thread (it does not check the value) but other threads will see foo==2 before the ten minutes is up. – alzee Aug 01 '16 at 19:18

1 Answers1

2

That is not guaranteed in general. Also that an update happens is not guaranteed, as no volatile is added to one of the fields. That would synchronize the caches of the threads, and also guarantee the order.

(I hope I am correct.)


Clarification (I hope)

The given scenario does not as much concern the java byte code handled by the jvm. It is (in general) not so that the compiler cleverly rearranges or interpretes byte code out of order. It is the just-in-time compiled code running in a thread with its local thread cache, duplicately holding common variables.

A volatile marked field ensures that those common variables are synchronized to all threads. Of course a single thread may execute code in any order as long as the result is okay.

y = ++x;

The actual execution of the following pseudoassembly

1. move from @x to register1
2. increment register1
3. move from register1 to @x
4. move from register1 to @y
5. synchronize @x and @y

Might be done quite differently on different processors. One or both variables might be cached in the thread memory itself, either needing a write to the far variable, or not.

Of course it is guaranteed that the same thread is handled gives a correct result. And noone sees, the order is irrelevant: 4 might become before 3 or be faster than 3 due to the memory.

If 3. and 4. were JIT compiled switched, the same thread would not see/detect any difference, but other threads might first see a change in y. That is without volatile.

This all is quite esoteric, too low-level. One might wonder that it came in the language specification, just like that a byte variable is stored in a 4 byte word internally. It deals with implementation issues, that indeed are relevant, like missing byte operations. When one is interested in the topic, take an assembler, maybe combined with C and try these things out. Otherwise keep away from unsafe programing.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • um .... execution order **is** guaranteed. Verily - but only within the **current** thread, another thread might *"see"* different things : http://stackoverflow.com/a/16629365/351861. Please dont write answers of which you arent sure about – specializt Aug 01 '16 at 08:37
  • 2
    @specializt the JIT compiler and the CPU are free to re-order these statements. Nothing prevents, nor would you want it to. – Peter Lawrey Aug 01 '16 at 08:39
  • ... only if the reordering "produces results consistent with a legal execution" - so it actually doesnt matter, the reordering itself is an implementation detail, consistent results are guaranteed - within the same thread. – specializt Aug 01 '16 at 08:43
  • @specializt yes, for different threads of course, as for a single thread a reordering is irrelevant (who is going to find out?). As you commented. My expressed doubt relates to such technicalities as you quoted. I like your corrective comments, thanks. Please answer questions too. – Joop Eggen Aug 01 '16 at 08:48
  • @JoopEggen: Thanks indeed. Would be really helpful if you could answer the second part too. – Farhan stands with Palestine Aug 01 '16 at 15:32
  • I thought the intermediary code does not have any registers but some JVM implementations use registers as they are faster then pushing/popping everythin onto/from the stack. Therefore it is probably implementation dependent I guess? – Roman Vottner Aug 01 '16 at 22:17
  • @RomanVottner I meant, that this official "misbehavior" is founded in Just-In-Time compilation of intermediate java byte code to machine instructions. Then L2 cache and out-of-order execution of instructions exist too. - As registers are glued on the CPU, and the stack is more general memory, often general purpose registers are faster. It is the most ofen seen ubiquitous processor category. For the JVM interpreter a pure stack machine does not make it slower and is beneficial to the real JIT compilation. – Joop Eggen Aug 02 '16 at 06:20