简体   繁体   中英

Safe publication through final

Even after going though this , I am still not clear about how usage of final causes safe publication in the below code. Can someone give an easy-to-understand explanation.

public class SafeListener
{
    private final EventListener listener;

    private SafeListener()
    { 
         listener = new EventListener()
         {  public void onEvent(Event e)
            {  doSomething(e); }
          };
    }

    public static SafeListener newInstance(EventSource source)
    {    
          SafeListener safe = new SafeListener(); 
          source.registerListener(safe.listener);
          return safe;
    }
}

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" .

In a nutshell, the specification for final (see @andersoj's answer) guarantees that when the constructor returns, the final field will have been properly initialized (as visible from all threads).

There is no such guarantee for non-final fields (which means that if another thread gets the freshly constructed object, the field may not have been set yet).

That this works is part of the JVM spec.

How it works would be a JVM implementation detail.

You can refer to JSL Final field or the object reachable through a final reference can't be reordered with the initial load of a reference to that object. It is visible to all other threads after its construction.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM