问题引出:
今天在看volatile的时候,自己写了个例子,
发现即使没有volatile,我程序也照常跑了
描述
首先看看这个情况的描述
第一个代码是有关何时以及如何使用volatile的示例,熟悉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;}
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,否则主线程将找不到flag变量的更改
但是如果下面这段代码,程序他,竟然看到了flag的变动
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();
}
问题的解决
自己动手修改了一下代码尝试了一下,
发现如果删除print,线程就看不到变化,
只要随随便便加一个print语句,线程就看到了变化
Thread t2=new Thread(()->{while(true) {
System.out.println("no");
if (amb != 0) {
System.out.println("SUc");
break;
}
}});
问题似乎变的清晰了,点开print的代码,
public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}
这里有一个synchronized ,synchronized大家都知道吧,重量级锁,线程将释放资源等待
线程执行到这里时,释放了自己的资源,发生了“线程切换”,线程的缓冲区就随之消失,
等到第二次执行到这里的时候,重新获取了变量的值
所以看起来似乎不用使用“volatile”