也许我希望表达的不是那么清楚,第一个案例是关于何时使用和如何使用的示例 volatile
,并且为了使程序成功运行,我们需要添加volatile。
第二种是希望表示,即使没有volatile,程序也能成功运行。我希望知道为什么没有“volatile”
在第一个样本中,使用挥发性物质的典型样本
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======");
}
}
}
启动后,除非使用volatile,否则主线程将找不到标志的更改
但是,在示例中,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
1条答案
按热度按时间57hvy0tb1#
在第二种情况下,可能是io语句刷新线程的缓冲区
如果我使用io语句(sout),它将成功工作。
就这样,我不断在println中寻找原因,我找到了真正的原因
同步导致线程切换
有了这个开关,线程的缓冲区很清晰,
所以thread2读取一个新值