考虑以下用Java编写的多线程代码:
共享变量:
boolean n; // non-volatile
volatile boolean v; // volatile线程1:
v = true;
System.out.println("n=" + n);线程2:
n = true;
System.out.println("v=" + v);假设最初是n = v = false。
现在:
v=false 的输出是否意味着 n=true的输出?n是不稳定的,会发生什么变化?n是java.util.List (因此n = true变成n.add("something")并将输出n=true转换为["something"]),会发生什么变化?v是AtomicBoolean,并且所有的读取和写入都是用compareAndSet语义执行的呢?你能根据Java内存模型来说明你的立场吗?
UPD:请把System.out.println("n=" + n)当作对n的读物。v也是如此。
UPD2:,您能对第1和第4种情况提供一些分析,如JSR-133秒所示。8?
发布于 2016-08-27 00:43:05
实际上有三种代码可以执行的方法:
// Thread 1 runs first
T1: v = true;
T1: System.out.println("n=" + n); // prints n=false
// Thread 2 runs second
T2: n = true;
T2: System.out.println("v=" + v); // prints v=true// They run in parallel, so assignments first, in any order
T1: v = true;
T2: n = true;
// Print statements second, in any order
T1: System.out.println("n=" + n); // may print n=true or n=false (depends on CPU caching)
// will print n=true if n is volatile
T2: System.out.println("v=" + v); // prints v=true// Thread 2 runs first
T2: n = true;
T2: System.out.println("v=" + v); // prints v=false
// Thread 1 runs second
T1: v = true;
T1: System.out.println("n=" + n); // may print n=true or n=false (depends on CPU caching)
// will print n=true if n is volatilev=false的输出是否意味着n=true的输出?
不是的。正如您在第三个场景中所看到的,n可以打印任意一个值。
如果n是不稳定的,会发生什么变化?
如注释所示,n将在场景2和3中打印true,而不是不确定的。
如果n是java.util.List (使n=true变为n.add(“某某物”),并将输出n=true转换为“某样东西”),那么会发生什么变化?
这假设在场景开始之前n已经是一个List,所以n的波动性并不重要。
n的打印是否会看到插入的值取决于列表的类型。如果不并发的列表,答案与问题1相同:它可能看到也可能看不到新的值。非并发列表的示例:
set()__,因为不能在这类列表中调用add() )如果列表是并发的,它将看到新的值。同时列出的例子:
发布于 2016-08-27 00:01:57
这里有两个因素。
volatile字段,但是synchronized的System.out.println调用--这是读写屏障在这两个线程中,您都在执行写入和读取操作。写障碍不能保证阅读障碍。
v=false的输出是否意味着n=true的输出?
如果你看到v=false,你可能会看到一个n=false,而visa反过来
如果n是不稳定的,会发生什么变化?
不太可能,您可能会看到行为的变化取决于您正在运行的体系结构,但是您仍然可以看到某些机器的不确定性行为。
如果n是java.util.List,会发生什么变化?
主要的变化是您正在替换一个写屏障,例如n = true使用一个读屏障n.method,这意味着您不再有一个写屏障(除了调用同步方法)
这样做意味着线程之间的一致性失败有更多的原因。
https://stackoverflow.com/questions/39175959
复制相似问题