Java: Is volatile / final required for reference to synchronized object?

后端 未结 5 777
陌清茗
陌清茗 2021-01-04 02:52

This seems a pretty basic issue, but I cannot find a clear confirmation.

Let\'s say I have a class properly synchronized in itself:

public class Sync         


        
5条回答
  •  礼貌的吻别
    2021-01-04 03:32

    This depends entirely on the context of how this variable is shared.

    Here is a simple example where it's fine:

    class SimpleExample {
        private String myData;
    
        public void doSomething() {
            myData = "7";
    
            new Thread(() -> {
                // REQUIRED to print "7"
                // because Thread#start
                // mandates happens-before ordering.
                System.out.println(myData);
            }).start();
        }
    }
    

    Your given examples may fall under this case. 17.4.5:

    • If x and y are actions of the same thread and x comes before y in program order, then hb(x, y).

    • A call to start() on a thread happens-before any actions in the started thread.

    In other words if the assignment to mySharedObject takes place on the same thread that starts the new thread, the new thread is mandated to see the assignment regardless of synchronization.

    However, if you expect, for example, that init could be called on a thread that is different from the one that calls doSomething, then you may have a race condition.

    public static void main(String[] args) {
        final OuterClass myOuter = new OuterClass();
    
        Thread t1 = new Thread( () -> myOuter.init(true)    );
        Thread t2 = new Thread( () -> myOuter.doSomething() );
    
        t1.start(); // Does t1#run happen before t2#run? No guarantee.
        t2.start(); // t2#run could throw NullPointerException.
    }
    

    The fact that SyncClass has synchronized methods is completely irrelevant with respect to guaranteed state of the mySharedObject reference. Reading that reference is performed outside the synchronized block.

    When in doubt, use final or volatile. Whichever is appropriate.

提交回复
热议问题