volatile 可见性的测试
volatile : 用在:线程共享且可能被修改的变量
1.保证变量的可见性 : 当一个变量被 volatile 修饰时,线程对该变量的修改会 立即写回主内存,同时其他线程的工作内存中该变量的缓存会 失效,必须重新从主内存读取最新值。
2.禁止指令重排序 编译器或 CPU 为了优化性能,可能会对指令进行重排序(不影响单线程结果,但可能破坏多线程正确性)。举例:单例模式的双重检查锁中,volatile 修饰实例变量,可避免 “指令重排序导致的未初始化实例被引用” 问题。
代码:
public class VolatileVisibilityTest {
// 测试时注释/打开 volatile 对比效果
static boolean flag = false;
public static void main(String[] args) {
// 线程1:循环等待 flag 变为 true
new Thread(() -> {
long i = 0;
System.out.println("线程1开始,flag初始值:" + flag);
// 循环内增加大量计算,迫使JVM优化(缓存flag)
while (!flag) {
i++;
}
System.out.println("线程1结束,flag已变为:" + flag + ",循环次数:" + i);
}, "线程1").start();
// 线程2:1秒后修改 flag 为 true
new Thread(() -> {
try {
Thread.sleep(1000); // 确保线程1先启动并进入循环
flag = true;
System.out.println("线程2已将flag修改为:" + flag);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "线程2").start();
}
}这里的代码中
while (!flag) { i++; } 循环计算,jvm中 jit即时编译会将其优化成 while(true) 使得经管 线程修改了状态,线程一还是1一意孤行,它不知道最新的状态
通过: volatile static boolean flag = false; 线程 2 修改 flag 后,线程 1 会立即感知到 flag 变为 true,退出循环并打印结束信息,体现 “可见性”。
其实如果:代码中加了打印语句也会可见的
public class VolatileVisibilityTest {
// 测试时注释/打开 volatile 对比效果
static boolean flag = false;
public static void main(String[] args) {
// 线程1:循环等待 flag 变为 true
new Thread(() -> {
long i = 0;
System.out.println("线程1开始,flag初始值:" + flag);
// 循环内增加大量计算,迫使JVM优化(缓存flag)
while (!flag) {
i++;
// 增加无意义计算,强化JVM对flag的缓存
if (i % 100000000 == 0) {
// 偶尔打印,避免JVM认为循环无意义而优化掉
System.out.println("线程1仍在等待...");
}
}
System.out.println("线程1结束,flag已变为:" + flag + ",循环次数:" + i);
}, "线程1").start();
// 线程2:1秒后修改 flag 为 true
new Thread(() -> {
try {
Thread.sleep(1000); // 确保线程1先启动并进入循环
flag = true;
System.out.println("线程2已将flag修改为:" + flag);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "线程2").start();
}
}System.out.println() 会间接引发线程上下文切换,进而导致线程重新从主内存读取变量值
System.out 是全局单例 println() 的锁对象是 this(即 System.out 本身)核心是:
其内部的
synchronized锁会引发线程阻塞 / 唤醒(上下文切换);更重要的是,
synchronized强制线程从主内存读取变量,相当于 “绕过了工作内存的缓存”,让无volatile的变量也能偶尔被刷新。
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 程序员阿政
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果