3

Refer to this blog and this topic.

It seems the code will be reorder even in single thread ?

public int hashCode() {
 if (hash == 0) { // (1)
     int off = offset;
     char val[] = value;
     int len = count;

     int h = 0;
     for (int i = 0; i < len; i++) {
         h = 31*h + val[off++];
     }
     hash = h;
  }
  return hash; // (2)
}

But its really confusing to me, why (2) could return 0 and (1) could be non-zero ?

If i use the code in single thread, this will even doen't work, how could it happens ?

Community
  • 1
  • 1
WoooHaaaa
  • 19,732
  • 32
  • 90
  • 138
  • This is a multithreading issue only. – Marko Topolnik May 29 '13 at 11:10
  • Him @MarkoTopolnik , How could reordering perform in multi-thread ? I'm not sure but i think the **reordering** is performed in bytecode which do nothing with threads ? – WoooHaaaa May 29 '13 at 11:15
  • Reordering definitely does not happen at the bytecode level; it's a JIT compiler-related issue. You are guarenteed to have sane behavior inside a single thread. – Marko Topolnik May 29 '13 at 11:16
  • @MarkoTopolnik, But why *reordering*'s behavior is different between multi-thread and single thread ? – WoooHaaaa May 29 '13 at 11:30
  • @MrROY: It is deviating from the main question here already. If you really want to ask that, then edit your question. – nhahtdh May 29 '13 at 12:23

2 Answers2

1

The first point of java memory model is:

Each action in a thread happens before every action in that thread that comes later in the program's order.

That's why reordering in single thread is impossible. As long as code is not synchronized such guaranties are not provided for multiple threads.

Have a look at String hashCode implementation. It first loads hash to a local variable and only then performs check and return. That's how such reorderings are prevented. But this does not save us from multiple hashCode calculations.

Mikhail
  • 4,175
  • 15
  • 31
  • I believe the reordering is not prevented in single threaded program. It just will not be noticed in single thread. – WoooHaaaa May 30 '13 at 06:28
0

First question:

Will reordering of instructions happen in single threaded execution?

Answer:

Reordering of instructions is a compiler optimization. The order of instructions in one thread will be the same no matter how many threads involved. Or: Yes in single threaded, too.

Second question:

Why could this lead to a problem in multi-threading but not with one thread?

Answer:

The rules for this reordering are designed to gurantee that there are no strange effects in single threaded or correctly synchronized code. That means: If we write code that's neither single threaded nor correctly synchronized there might be strange effects and we have to understand the rules and take care to avoid those effects.

So again as the auhor of the orginal blog said: Don't try if you're not really sure to understand those rules. And every compiler will be tested not to break String.hashCode() but compliers won't be tested with your code.

Edit: Third question:

And again what is really happening?

Answer:

As we look at the code it will deal fine with not seeing changes of another thread.So the first thing we have to understand is: A method doesn't return a variable nor a constanst nor a literal. No a method return what's on top of the stack when the programm counter is reset. This has to be initialized at some point in time and it can be overwritten later on. This means it can be initialized first with the content of hash (0 now) then another thread finishes calculation and set hash to something and then the check hash == 0 happens. In turn the return value is not overwritten anymore and 0 is returned.

So the point is: The return value can change independently of the returned variable as it is not the same. Modern programming language make it look the same to make our lives easier. But this abstraction as wholes when you don't adhere to the rules.

Bernd Ebertz
  • 1,317
  • 8
  • 10
  • Re-ordering may happen in single threaded environment, but it will not create unexpected behaviour, since the unexpected behaviour is due to the field being modified in other thread, while the current thread is optimized and does not see the updated value. – nhahtdh May 29 '13 at 17:59
  • @nhahtdh Hopefully my edit make the point a little bit clearer. – Bernd Ebertz May 29 '13 at 19:12
  • Where exactly does `check hash == 0 happens` performed ? – WoooHaaaa May 30 '13 at 02:18
  • I always believe `check hash == 0` will first load hash into the top of thread stack(which will overwrite the return value), isn't it? – WoooHaaaa May 30 '13 at 02:19
  • No, a comparison is not a method call. It won't use stack, but processor registers. Comparison of registers is a single processor instruction. In fact the returned value is kept in a register before being returned. However, register or stack is not the point. The point is, what is returned is independent from the variable. – Bernd Ebertz May 30 '13 at 18:32