本文介绍了使引用变量易变,在Java中也使它的所有字段也易变吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经读到使引用变量为volatile并不会使其内部字段为volatile.但是我尝试使用下面的示例,其中看起来像volatile性质也适用于类的内部字段.

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:-//将字段标志"设置为true的用户类.

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:-

MyRunnableThread1.java:-

在这里,我将用户"设置为易失性,而不是将其内部字段标志"设置为易失性

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

子线程在"while(this.user.isFlag())"处连续循环.

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:-

ThreadDemo.java:-

在主线程中,我们将"User"对象的字段"flag"的值设置为false终止子线程中的循环

in main thread we sets the value of field "flag" of "User" object as falseto 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:-

主线程已启动子线程:Thread1已启动主线程完成子线程:线程1完成

main thread startedchild thread:Thread1 startedmain thread finishedchild thread:Thread1 finished

在上面的示例中,我在"MyRunnableThread1.java"类中将"user"变量设置为volatile.用户对象的字段"flag"在实例化时为true.在开始连续执行循环的子线程之后,主线程将用户对象的字段"flag"的值更改为false.但是这里"flag"字段不是volatile,而是"user"引用变量是volatile.但是这里主线程中"flag"字段的值变化仍然反映在子线程中.它的行为就像"flag"字段也是易挥发的.任何人都可以帮助解决上述问题吗?

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??

推荐答案

来自JLS:

Java编程语言允许线程访问共享 变量(第17.1节).通常,要确保共享变量是 一致且可靠地更新线程,应确保它具有 通过获得一个锁来排他地使用这些变量, 通常,对这些共享变量强制执行互斥.

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.

Java编程语言提供了第二种机制,volatile 字段,这比出于某些目的而锁定更方便.

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

一个字段可以声明为volatile,在这种情况下是Java内存模型 确保所有线程看到变量的一致值 (§17.4).

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

但是对象不是变量.那么在您的情况下,user的值是一致的,这意味着所有线程都看到相同的引用,而不是它们的内部内容具有相同的值.

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.

这篇关于使引用变量易变,在Java中也使它的所有字段也易变吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-23 22:16