How do final fields prevent other threads from seeing partially
constructed objects?
I was looking into creating an immutable datatype that has final fields
(including an array that is constructed and filled prior to being assigned
to the final member field), and noticed that it seems that the JVM is
specified to guarantee that any other thread that gets a reference to this
object will see the initialized fields and array values (assuming no
pointers to this are published within the constructor, see What is an
"incompletely constructed object"? and How do JVM's implicit memory
barriers behave when chaining constructors?).
I am curious how this is achieved without synchronizing every access to
this object, or otherwise paying some significant performance penalty.
According to my understanding, the JVM can achieve this by doing the
following:
Issue a write-fence at the end of the constructor
Publish the reference to the new object only after the write-fence
Issue a read-fence any time you refer to a final field of an object
I can't think of a simpler or cheaper way of eliminating the risk of other
threads seeing uninitialized final fields (or recursive references through
final fields).
This seems like it could impose a severe performance penalty due to all of
the read-fences in the other threads reading the object, but eliminating
the read-fences introduces the possibility that the object reference is
seen in another processor before it issues a read-fence or otherwise sees
the updates to the final fields.
Does anyone know how this works? And whether this introduces a significant
performance penalty?
No comments:
Post a Comment