Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
810 views
in Technique[技术] by (71.8m points)

multithreading - Does making reference variable volatile, make all its field volatile too in java?

I have read that making reference variable volatile, does not make its inner fields volatile.But i tried with below example where it looks like volatile nature is applied to inner fields of class as well.

User.java:- // user class having field "flag" set as true.

public class User {

    private boolean flag=true;

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }
} 

MyRunnableThread1.java:-

here i have made "user" as volatile and not its inner field "flag" as volatile

child thread is continuously in loop at "while(this.user.isFlag())".

public class MyRunnableThread1 implements Runnable {

    private String threadName;
    private  volatile User  user; 

    public MyRunnableThread1(String threadName,User user)
    {
        this.threadName=threadName; 
        this.user=user;
    } 

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    @Override
    public void run() {

        System.out.println("child thread:"+threadName+" started");

        while(this.user.isFlag()) {

        }
        System.out.println("child thread:"+threadName+" finished");
    }
}

ThreadDemo.java:-

in main thread we sets the value of field "flag" of "User" object as false to terminate the loop in child thread

public class ThreadDemo {

    public static void main(final String[] arguments) throws InterruptedException {

        System.out.println("main thread started");

        User user=new User(); 
        MyRunnableThread1 myRunnableThread1=new MyRunnableThread1("Thread1",user);
        Thread t=new Thread(myRunnableThread1);
        t.start();

        try {
            Thread.sleep(6000);
        }
        catch(Exception e) {
            System.out.println("exception in sleep:"+e);
        }

        myRunnableThread1.getUser().setFlag(false);

        System.out.println("main thread finished"); 
    }
}

o/p:-

main thread started child thread:Thread1 started main thread finished child thread:Thread1 finished

In above example I have made "user" variable as volatile in "MyRunnableThread1.java" class. User object has field "flag" which is true at time of instantiation. After starting the child thread where it continuously execute the loop , the main thread changes the value of field "flag" of user object to false. But here field "flag" is not volatile instead the "user" reference variable is volatile.But still here the change in value of field "flag" in main thread is reflected in child thread.It behaves as if field "flag" is also volatile. can anyone help with above issue??

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

From JLS:

8.3.1.4. volatile Fields

The Java programming language allows threads to access shared variables (§17.1). As a rule, to ensure that shared variables are consistently and reliably updated, a thread should ensure that it has exclusive use of such variables by obtaining a lock that, conventionally, enforces mutual exclusion for those shared variables.

The Java programming language provides a second mechanism, volatile fields, that is more convenient than locking for some purposes.

A field may be declared volatile, in which case the Java Memory Model ensures that all threads see a consistent value for the variable (§17.4).

But objects are not variables. Then in your case what is consistent is the value of user which means that all threads see the same reference, not that they observe the same values for its inner content.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...