Re: Thread safety and atomic assignment (again)
 
"Mike Schilling" <mscottschilling@hotmail.com> wrote in message 
news:cF4Sj.457$J16.156@newssvr23.news.prodigy.net...
Matt Humphrey wrote:
As a clearer example of this point, if the object used for setValue
had non-volatile fields that were not assigned in the constructor,
there is nothing that guarantees that the updated values of those
fields will be visible in a different thread.
Unless, of coujrse, the object itself guarantees that by synchronizing the 
getter(s) and setter(s).
I agree, but this raises to my mind a case whether synchronized is necessary 
or not.  The case I'm thinking of is like this:
class Factorization {
  private int [] factors;
  public Factorization (int value) {
    factors = new int [20];
    computeFactors (value);
  }
  public void computeFactors (int value) {
    // Internal code that populates the array
  }
  public int getTotal () {
    if (factors == null) return 0;
    int total = 0;
    for (int i =0; i < factors.length; ++i) {
     total += factors[i];
    }
    return total;
}
class MathBox {
  private volatile Factorization factorization;
  public Factorization getF () { return factorization; }
  public void setF (Factorization f) { factorization = f; }
}
static MathBox sharedMathBox = new MathBox ();
// Writer thread
for (int i = 0; i < 100; ++i) {
  Factorization factorization = new Factorization (i);
  // Alternate position for computeFactors ()
  sharedMathBox.setF (factorization);
}
// Reader thread
for (int i = 0; i < 100; ++i) {
  Factorization factorization = sharedMathBox.getF ();
  System.out.println ("" + factorization.getTotal ());
}
Despite the contrivance of 2 totally unsynchronized threads, what is not 
clear to me is what the read thread will see for the values for the 
factorization.  The volatile keyword ensures that the factorization 
reference arrives safely, but it doesn't guarantee the fields.  The fields 
are assigned within the execution of the constructor, but I don't think 
that's sufficient; I don't think it counts as the visibility of the initial 
value.
Will the reader sometimes see a total of 0 because factors is null?  Will it 
sometimes see an inconsistent result because not all of the values have been 
updated?  Or will it always be up-to-date because it falls within the 
natural ordering of the constructor?
It does seem certain that if computeFactors is moved out of the constructor 
and into the loop at the marked position that the reader thread may 
sometimes see inconsistent results.  Synchronizing computeFactors would 
ensure that the reader always sees the up-to-date values.
I tested volatile on a 2-processor hyperthreaded system a couple years ago 
and I could not get non-volatile values to fail.  I would like to know what 
the correct model is for this case, but I would only trust an empirical test 
that actually showed a failure.  (The test might not fail because of CPU 
caching, JIT performance, etc.)
Matt Humphrey http://www.iviz.com/