问题引出:

今天在看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;}
@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,否则主线程将找不到flag变量的更改

println导致的线程缓冲区刷新|一个volatile引起的思考_python

但是如果下面这段代码,程序他,竟然看到了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;
}
}});

println导致的线程缓冲区刷新|一个volatile引起的思考_javascript_02

问题似乎变的清晰了,点开print的代码,

public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}

这里有一个synchronized ,synchronized大家都知道吧,重量级锁,线程将释放资源等待

线程执行到这里时,释放了自己的资源,发生了“线程切换”,线程的缓冲区就随之消失,

等到第二次执行到这里的时候,重新获取了变量的值

所以看起来似乎不用使用“volatile”


更多内容详见微信公众号:Python研究所

println导致的线程缓冲区刷新|一个volatile引起的思考_python_03