Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

During initialization of a shared object, the object must be accessible only to the thread constructing it. However, the object can be published safely (that is, made visible to other threads) once its initialization is complete. The Java Memory Model (JMM) allows multiple threads to observe the object after its initialization has begun but before it has concluded. Consequently, programs must prevent publication of partially initialized objects.

...

  • The helper reference as null
  • A fully initialized Helper object with the n field set to 42
  • A partially initialized Helper object with an uninitialized n, which contains the default value 0

In particular, the JMM permits compilers to allocate memory for the new Helper object and to assign a reference to that memory to the helper field before initializing the new Helper object. In other words, the compiler can reorder the write to the helper instance field and the write that initializes the Helper object (that is, this.n = n) so that the former occurs first. This can expose a race window during which other threads can observe a partially initialized Helper object instance.

...

Synchronizing both methods guarantees that they cannot execute concurrently. If one thread were to call initialize() just before another thread called getHelper(), the synchronized initialize() method would always finish first. The synchronized keywords establish a happens-before relationship between the two threads. Consequently, the thread calling getHelper() would see either the fully initialized Helper object or an absent Helper object (that is, helper would contain a null reference). This approach guarantees proper publication both for immutable and mutable members.

...

However, this solution requires the assignment of a new Helper instance to helper from Foo's constructor. According to the Java Language Specification, §17.5.2, "Reading Final Fields During Construction" [JLS 2005]

A read of a final field of an object within the thread that constructs that object is ordered with respect to the initialization of that field within the constructor by the usual happens-before rules. If the read occurs after the field is set in the constructor, it sees the value the final field is assigned; otherwise, it sees the default value.

...

According to JSR-133, Section 9.2.3, "Static Final Fields" [JSR-133 2004]

The rules for class initialization ensure that any thread that reads a static field will be synchronized with the static initialization of that class, which is the only place where static final fields can be set. Thus, no special rules in the JMM are needed for static final fields.

...

The JMM guarantees that any final fields of an object are fully initialized before a published object becomes visible [Goetz 2006a]. By declaring n final, the Helper class is made immutable. Furthermore, if the helper field is declared volatile in compliance with rule VNA01-J. Ensure visibility of shared references to immutable objects, Helper's reference is guaranteed to be made visible to any thread that calls getHelper() only after Helper has been fully initialized.

...

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

TSM03-J

medium

probable

medium

P8

L2

Bibliography

[API 2006]

 

[Bloch 2001]

Item 48. Synchronize access to shared mutable data

[Goetz 2006a]

Section 3.5.3, Safe Publication Idioms

[Goetz 2007]

Pattern #2, One-Time Safe Publication

[JPL 2006]

14.10.2, Final Fields and Security

[Pugh 2004]

 

...

      Rule 12: Thread-Safety Miscellaneous (TSM)      Rule 13: Input Output (FIO)Image Added      Image Added