也许我希望表达的不是那么清楚,第一个例子是关于何时以及如何使用
的示例,为了使程序成功运行,我们需要添加易失性。第二种是希望表达,即使没有易失性,程序也会成功运行。我希望知道为什么在没有“不稳定”的情况下会发生这种情况
在第一个示例中,使用易失性的典型示例
public static int num=1;
public static class MyThread extends Thread {
// flag
private boolean flag = false ;
public boolean isFlag() { return flag;}
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) { e.printStackTrace();
}
// change flag to true
this.flag = true ;
System.out.println("flag=" + flag);
this.flag=true;
}
}
// main
static void testWithOutVolatile(){
MyThread t=new MyThread();
t.start();
while(true) {
boolean is=t.flag;
if (is) {
System.out.println("run======");
}
}
}启动后,主线程将找不到更改标志,除非使用易失性。
然而,在示例中,thread2意外地得到了标志的更改,为什么会发生这种情况?
static int amb=0;
static void testSimple(){
Thread t1=new Thread(()->{
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
amb++;
});
Thread t2=new Thread(()->{while(true) {
if (amb == 0) {
System.out.println("no");
}
if (amb != 0) {
System.out.println("SUc");
break;
}
}});
t2.start();
t1.start();
}经过一次尝试,我发现如果我删除代码
if (amb == 0) {
System.out.println("no");
}它会像我想的那样运行,thread2无法得到更改。
谢谢你的回答,QwQ
发布于 2020-12-26 10:36:11
在第二种情况下,io语句可能刷新线程的缓冲区
Thread t2=new Thread(()->{while(true) {
System.out.println("no");
if (amb != 0) {
System.out.println("SUc");
break;
}
}});如果我使用io语句(Sout),它将成功地工作。

通过这种方式,我不断地在println中找到理由,我也找到了真正的原因。
public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}同步导致线程切换
通过开关,线程的缓冲区是透明的,
所以thread2读取了一个新的值
https://stackoverflow.com/questions/65455228
复制相似问题