Edited to add: Interesting perspective on the origins of Java and JSR-133's final
behavior.
Canonical reference for how final
works in the new JMM, for safe publication: http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#finalRight
On simple review, I think your code represents "safe" publication to the EventSource source
object, which presumably will be fielding event callbacks to listener
in a different thread. You are guaranteed that threads operating on the safe.listener
reference passed will see a fully-initialized listener
field. This does not make any further guarantees about other synchronization issues associated with calls to onEvent
or other interactions with the object's state.
What is guaranteed by your code is that, when SafeListener
's constructor returns a reference inside the static method, the listener
field will not be seen in an unwritten state (even if there is no explicit synchronization). For example: Suppose a thread A calls newInstance()
, resulting in an assignment to the listener
field. Suppose that a thread B is able to dereference the listener
field. Then, even absent any other synchronization, thread B is guaranteed to see the write listener = new EventListener()...
. If the field were not final
, you would not receive that guarantee. There are several (other) ways of providing the guarantee (explicit synchronization, use of an atomic reference, use of volatile) of varying performance and readability.
Not everything that's legal is advisable. Suggest you take a look at JCiP and perhaps this article on safe publication techniques.
A recent, related question is here: "Memory barriers and coding...", "Java multi-threading & Safe Publication".
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…