7

Possible Duplicate:
How to simulate constructor race conditions?
How to demonstrate race conditions around values that aren't published properly?

I got the following code from 《java concurrency in practice》:

public class Holder{

  private int n;
  public Holder(int n){this.n = n;}
  public void assertSanity(){
     if(n != n) throw new AssertionError("This statement is false.");

  }


}

I am just wondering the condition n != n, is this could be true under a certain circumstance?

Community
  • 1
  • 1
Foredoomed
  • 2,219
  • 2
  • 21
  • 39

5 Answers5

2

My guess is that you are asking something similar to these questions:

I'm guessing the book is talking about the possibility of sharing a reference to an object before it is completely constructed, an act referred to is improper publishing.

Suppose that n != n is broken down into the following steps:

Access n on the right side of the operand
Access n on the left side of the operand
Compare values

Then it follows that it is not hard to imagine a case in which the value of n is changed between the first two steps. Now I know what you are thinking, "but n is never changed". Actually, it is, because two threads could share access to an instance of Holder before the constructor for that instance has completely run.

Community
  • 1
  • 1
Tim Bender
  • 20,112
  • 2
  • 49
  • 58
0

Presumably the compiler would optimize this away as always false, but if not then yes, in a multithreaded environment it could return true.

Assume n on the left is copied to a a register. Then the current thread is interrupted, the next thread modifies n, then we return to the first thread. Now the right-side n is copied to a register and then the comparison operation (on the two registers) is invoked.

In this case they would be different.

EDIT: If you look at the bytecode in nhantdh's comment below you'll see that two loads are performed on n, so an interrupt with modification between the two can cause the expression to evaluate to true.

par
  • 17,361
  • 4
  • 65
  • 80
  • The compiler does not optimize this: disassembling shows byte code: 0: aload_0 1: getfield #2; //Field n:I 4: aload_0 5: getfield #2; //Field n:I. 8: if_icmpeq 21 As you can see, n is loaded twice, then the comparison still happens. – nhahtdh Sep 24 '12 at 05:53
  • @nhahtdh - A future compiler might however, as well as some other JVM implemented by that you've never seen. I point out that a compiler *could* optimize it out to illustrate that you might never be able to generate a test condition where this evaluates to true, but that would mask the concurrency-programming problem being discussed, which boils down to a race condition on an improperly protected resource. – par Sep 24 '12 at 05:57
  • I am aware that they might optimize it away in the JVM (the JIT compiler) in the other comment. The compiler that generate byte code will not, is what I'm pointing out. – nhahtdh Sep 24 '12 at 06:02
  • @nhahtdh - Well it is not a very interesting thing to point out, since the bytecode compiler does very little optimization anyway. In reality all of the heavy optimization in a Hotspot JVM is performed by the JIT compiler – Stephen C Sep 24 '12 at 06:42
  • @StephenC: Agreed. Most optimization probably happens within the JVM anyway. – nhahtdh Sep 24 '12 at 06:43
0

I guess in theory it's possible since n is not volatile. That means that a thread could construct a Holder object, but the value set for n will not be visible to a different thread running on a different core that invokes the comparison operation.

Tudor
  • 61,523
  • 12
  • 102
  • 142
  • It is possible if `n` is volatile too. The expression evaluation is not an atomic action. – Stephen C Sep 24 '12 at 06:14
  • @Stephen C: I can see what you're saying, but I guess that would really be impossible to reproduce. – Tudor Sep 24 '12 at 06:15
  • Not impossible. In fact, on a multi-core system it would probably be quite easy to reproduce if you wrote a program specifically for that purpose. – Stephen C Sep 24 '12 at 06:22
0

The value will always be the same.

As long as the variable is a primitive type, the variable is non static and you have no setter, you can create as many class instances as you wish. the instances will never share the same "object"/instance in variable 'n'.

if you change the value after the contructor call again, the value can be different, like setter or reflection.

Markus Lausberg
  • 12,177
  • 6
  • 40
  • 66
-2

I know this expression from C++. It can be true if n is not a number. See Checking if a double (or float) is NaN in C++

Community
  • 1
  • 1
ChaosCakeCoder
  • 367
  • 1
  • 8