1.先看一个案例
public class VolatileTest {
public static boolean IS_TRUE = true;
void m() {
while (IS_TRUE) {
}
System.out.println("end");
}
public static void main(String[] args) throws InterruptedException {
VolatileTest tv = new VolatileTest();
// 开启一个线程,
new Thread(() -> tv.m()).start();
Thread.sleep(1000);
// 开启一个线程,修改静态变量
new Thread(() -> IS_TRUE = false).start();
}
}
程序未正常退出,陷入死循环了,原因是因为static无法保证工作区与主存区变量值的一致性。
2.在看下volatile
public class VolatileTest {
public volatile static boolean IS_TRUE = true;
void m() {
while (IS_TRUE) {
}
System.out.println("end");
}
public static void main(String[] args) throws InterruptedException {
VolatileTest tv = new VolatileTest();
// 开启一个线程,
new Thread(() -> tv.m()).start();
Thread.sleep(1000);
// 开启一个线程,修改静态变量
new Thread(() -> IS_TRUE = false).start();
}
}
把变量用volatile修饰后,程序正常退出。这是因为第二个线程修改值后,第一个线程重新从主内存中获取了新值。
3.在while循环中使用System.out.println()
public class VolatileTest {
public static boolean IS_TRUE = true;
void m() {
while (IS_TRUE) {
System.out.println("while");
}
System.out.println("end");
}
public static void main(String[] args) throws InterruptedException {
VolatileTest tv = new VolatileTest();
// 开启一个线程,
new Thread(() -> tv.m()).start();
Thread.sleep(1000);
// 开启一个线程,修改静态变量
new Thread(() -> IS_TRUE = false).start();
}
}
程序也正常退出。疑惑了很久。最终打开源码
public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}
发现因为println方法使用了synchronized。使用了 synchronized 上锁会做以下操作:
1.获得同步锁;
2.清空工作内存;
3.从主内存拷贝对象副本到工作内存;
4.执行代码(计算或者输出等);
5.刷新主内存数据;
6.释放同步锁。
值得一提的是volatile保证可见性,但不保证原子性。synchronized不且保证可见性,也保证原子性。
欢迎扫描下面图片关注我的个人公众号,回复“资源”可以获取java核心知识整理和经典书籍