volatile问题

螃蟹夹夹夹 2019-06-10 11:22:24
public class Main {
int num = 0;
public void addTo60() {
this.num += 60;
}
public static void main(String[] args) throws InterruptedException {
Main main = new Main();
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
main.addTo60();
System.out.println(main.num);
}
});
t.start();
while (main.num == 0) {

}
}
}

以上代码会进入死循环,如果num 变量加上volatile就不会死循环/
而以下的代码,打印出的是60,并没有出现可见性问题,用while循环就会出现可见性问题,这该怎么解释

public class Main {
int num = 0;
public void addTo60() {
this.num += 60;
}
public static void main(String[] args) throws InterruptedException {
Main main = new Main();
Thread t = new Thread(new Runnable() {
@Override
public void run() {
main.addTo60();
}
});
t.start();
Thread.sleep(10);
System.out.println(main.num);
}
}
...全文
129 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
宾灬 2019-06-14
  • 打赏
  • 举报
回复
volatile 保证变量在线程之间的可见性。你需要了解,java线程的工作内存和主存。看一下 Java并发编程的艺术这本书,有对volatile的详细描述。看了之后相信你会有答案的。
qq_39936465 2019-06-11
  • 打赏
  • 举报
回复
引用 楼主 qq_41229913 的回复:
以上代码会进入死循环,如果num 变量加上volatile就不会死循环/ 而以下的代码,打印出的是60,并没有出现可见性问题,用while循环就会出现可见性问题,这该怎么解释
volatile 是同步变量,jvm为了程序执行效率,不会没事就去检查变量的值是否改变,而同步就是让程序时刻去检测变量的最新值,同步就会牺牲效率。
qq_39936465 2019-06-11
  • 打赏
  • 举报
回复
线程和main,是2个不同的进程,你的print语句是写在线程中的,如果不同步的话和主程序中的num还是有差别的,你可以在while循环中添加打印num的语句

public class Main {
    int num = 0;
    public void addTo60() {
        this.num += 60;
    }
    public static void main(String[] args) throws InterruptedException {
        Main main = new Main();
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                main.addTo60();
                System.out.println(main.num);
            }
        });
        t.start();
        while (main.num == 0) {
            System.out.println(main.num);
        }
    }
}
你可以看到当while在执行时,线程也在同步执行,这时候主程序的num还是0,当线程执行完改变num数据后,主程序中的print语句才会收到数据改变的信息,打印60然后退出循环。
imiMi_ 2019-06-11
  • 打赏
  • 举报
回复
println方法是同步方法,被synchronized包裹的,可以点进去看一下,num传进去时会去读取最新值。

62,615

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧