一直有个共享变量可见性的问题搞不懂,进来聊聊憋

2016-05-26 10:37:53 +08:00
 honam
public class NoVisibility{
	private static boolean ready;
	private static int number;

	private static class ReaderThread extends Thread{
		public void run(){
			while(!ready){
				Thread.yield();
			}
			System.out.println(number);
		}
	}

	public static void main(String[] args){
		new ReaderThread().start();
		number = 42;
		ready = true;
	}
}

上代码,这是并发编程实践里面的一个例子(清单 3.1 ),然后这段代码可能出现这种情况:可能一直保持循环。“因为对于读线程来说, ready 的值可能永远不可见”。我就纳闷了,怎么会永远不可见?你说一阵子不可见我能理解,真的会永远不可见吗?

3324 次点击
所在节点    Java
10 条回复
doing
2016-05-26 11:35:05 +08:00
每个线程有自己单独的工作内存,操作 ready 变量 会把 ready 变量从主内存 复制到自己的工作内存中去操作。操作完后,会写回主内存。

在这个过程,可能就会不可见。 A 线程改了 ready 变量的值,但还没写回主内存。或者,新的 B 线程还没重新去主内存获取 ready 变量。

我是这样理解的。
honam
2016-05-26 11:59:58 +08:00
@doing 感谢你的回答,“ A 线程改了 ready 变量的值,但还没写回主内存。或者,新的 B 线程还没重新去主内存获取 ready 变量。 ”是会这样,但是终究会写回内存 或者 会去主内存获取新值到工作内存吧?这两个操作难道都有可能会被终止掉?
incompatible
2016-05-26 12:04:46 +08:00
@honam 这个循环中的 ready 在编译后似乎会被优化成局部产量,初始化一次后就不变了,永远拿不到其他线程修改后的值。
honam
2016-05-26 12:08:37 +08:00
@incompatible 谢谢回答,顺求相关资料,书里面一句带过没说原因好头痛。
incompatible
2016-05-26 12:26:34 +08:00
@honam 周志明「深入理解 Java 虚拟机」,里面有一整章是讲这个的。
incompatible
2016-05-26 12:30:09 +08:00
@honam 我上面说编译期被优化不是主要原因。主要原因还是 1 楼说的那样。 A 和 B 操作之间没有 Barrier ,所以 B 读不到 A 的更改。给 ready 加了 volatile 后就产生了一个 Barrier , B 就可以读到了。
honam
2016-05-26 12:42:48 +08:00
@incompatible 我再问一个 volatile 的问题,如果变量不加这个修饰关键字,这个变量是不是不会在某个线程的工作内存失效,或者说,不会去主内存里面拿新的值?如果是我就明白了,如果不是,那还是回到我回答 1 楼的问题。。。
hadixlin
2016-05-26 12:57:44 +08:00
@honam 这个答案是不确定的,依赖 JVM 的具体实现.但是 volatile 的语义是虚拟机规范里面写明的,所有的 JVM 都必须实现该语义.
所以不用纠结变量什么时候去主存拿新值,只要知道没有 volatile 或者其他内存屏障,被多线程共享的变量的值是不可靠的.
anexplore
2016-05-26 13:21:45 +08:00
我的考虑是,在 run()中 while(!ready)并没有改变 ready 的值,那么编译器是否会直接将其优化成 tmp = !ready; while(tmp),从而导致其一直运行
SoloCompany
2016-05-27 02:07:28 +08:00
没有 violate 也没有 synchronized 当然有可能永远看不见变化
但具体行为依赖于 jvm 实现而不是编译器
在真正的多核环境下并且每个核心都有独立缓存的执行条件下, ReaderThread 线程执行的工作区内存有可能永远都得不到更新

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

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

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

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

© 2021 V2EX