大佬们求解释一段 Java 代码

2017-08-19 23:27:22 +08:00
 microhz

public class MyRun implements Runnable {

	private boolean stop;

	MyRun(boolean status) {
		this.stop = status;
	}
	@Override
	public void run() {
		while(!stop) {
			// System.out.println("running");
		}
		System.out.println("stop");
	}
	public boolean isStop() {
		return stop;
	}
	public void setStop(boolean stop) {
		this.stop = stop;
	}
}


// 测试代码
MyRun myRun = new MyRun(false);
new Thread(myRun).start();
Thread.sleep(1000);// 等待线程执行
myRun.setStop(true);

上面这段代码 while 语句内容里注释掉和不注释会不会打印 stop.为什么?

1899 次点击
所在节点    问与答
7 条回复
iEverX
2017-08-20 05:01:00 +08:00
stop 应该加 volatile,保证主线程的修改对子线程是可见的

如果不加 volatile,
1. 注释的情况,子线程没有从主内存中同步变量,子线程的值一直是 false 没有变
2. 不注释时,println 方法内部有个 sychronized 块,会同步主内存中的数据
microhz
2017-08-20 10:19:47 +08:00
@iEverX 我知道加 volatile 保证可见性肯定能终止循环,我也看了 println 的源码,的确是加了同步控制:
public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}
它加锁的是 PrintStream 对象,需要保证可见性的是 MyRun 对象的属性不是么
electric
2017-08-20 12:29:15 +08:00
一个很好的 Java 转 Python 的理由!
microhz
2017-08-20 13:03:50 +08:00
@electric Python 不适合做服务器开发
iEverX
2017-08-20 13:46:14 +08:00
@microhz 我之前也奇怪这点,查了好久
synchronized 会同步已失效的本地缓存,而不仅仅是其 lock 的变量

http://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4.1 17.1 节
https://docs.oracle.com/javase/specs/jvms/se6/html/Threads.doc.html 8.6 节
microhz
2017-08-21 13:15:38 +08:00
@iEverX 看看这篇文章吧,就是不知道讲的对不对 http://www.cnblogs.com/cookiezhi/p/5774583.html
iEverX
2017-08-21 21:50:50 +08:00
@microhz 感觉这个更靠谱

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/384263

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX