既然你点进来了,那就证明你知道volatile的作用是线程共享。
那么请见下面例子:
public class Warehouse extends Thread{
boolean flag = true;
@Override
public void run() {
while (true) {
if (!flag) {
break;
} else {
System.out.println(flag);
}
}
}
public static void main(String[] args) throws InterruptedException {
Warehouse warehouse = new Warehouse();
warehouse.start();
Thread.sleep(1000);
warehouse.flag=false;
}
}
请问线程是否会终止?
答案是会,这里有人可能会感到奇怪,问什么?我也是困惑了好久,感觉这并不符合逻辑啊。后来发现原来是因为System.out.println搞的鬼,我们注释掉这句代码就可以实现效果。我们来看一下System.out.println他的源代码就明确了。
public void println(boolean x) {
synchronized (this) {
print(x);
newLine();
}
}
public void print(boolean b) {
write(b ? "true" : "false");
}
private void write(String s) {
try {
synchronized (this) {
ensureOpen();
textOut.write(s);
textOut.flushBuffer();
charOut.flushBuffer();
if (autoFlush && (s.indexOf('\n') >= 0))
out.flush();
}
}
catch (InterruptedIOException x) {
Thread.currentThread().interrupt();
}
catch (IOException x) {
trouble = true;
}
}
JMM关于synchronized的两条规定:
1)线程解锁前,必须把共享变量的最新值刷新到主内存中
2)线程加锁时,将清空工作内存中共享变量的值,从而使用共享变量时需要从主内存中重新获取最新的值
(注意:加锁与解锁需要是同一把锁)
通过以上两点,可以看到synchronized能够实现可见性。同时,由于synchronized具有同步锁,所以它也具有原子性
所以使用了synchronized就已经保证了数据的可见性。这个坑货,忽然想到这可以作为一道面试题23333333。