在研究Java并发, 内存模型时, 遇到了一些问题?
public class VolatileDemo {
final static int MAX = 5;
static int initVal = 0;
static volatile int b=0;
public static void main(String[] args) {
new Thread(() -> {
int localVal = initVal;
while (localVal < MAX) {
if (initVal != localVal) {
b++;
System.out.printf("The iniVal is updated to [%d]\n", initVal);// A步骤
localVal = initVal;
}
}
}, "Reader").start();
new Thread(() -> {
int localVal = initVal;
while (localVal < MAX) {
System.out.printf("The initVal will be cahnged to [%d]\n", ++localVal);
initVal = localVal;
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "Updater").start();
}
}
以上的代码中, A 步骤永远不会发生(我测试了很多次, 我知道如果给变量加了volatile之后可以解决这个问题)。为什么?
- 为了防止localVal = initVal;指令重排到if之前, 我在他们之前加了一个volatile 变量
- 因此我怀疑是内存上的原因:但是我加了一个sleep, 这个时间完全足够工作内存到主内存中取数据, 但是还是没有什么作用
- 最后, 我怀疑是什么原因导致initVal变量一直使用的是工作变量(没有从主内存中刷新过来(虽然我认为不可能)), 没有从主内存中获取最新的值: 但是, 如果是这样, 那下面的例子为什么会不断访问获取主内存中的值呢?因此而导致结果还小
public class UnsafeThread implements Runnable {
private static int count = 0;
public void increase(){
count++;
}
public void run() {
for (int i = 0; i < 1000000000; i++) {
increase();
}
}
public static void main(String[] args) {
UnsafeThread myThread = new UnsafeThread();
Thread thread1 = new Thread(myThread);
Thread thread2 = new Thread(myThread);
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
System.out.println(count);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
感谢你能阅读到这, 如果知道答案, 望解惑一二, 谢谢