关于死循环中打印语句System.out.println()会跳出死循环的问题

有如下代码:

package logTest;

import lombok.extern.slf4j.Slf4j;

/**
 * @Author:wjy
 */
@Slf4j(topic = "c.test")
public class Test9_volitile {
    static boolean run = true;

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            while (run) {
                
            }
        });
        t1.start();

        Thread.sleep(1000);
        log.debug("停止 t");
        run = false;
    }
}

可以看到,代码运行后会进入死循环

这是因为当 t1 线程刚从主内存读取了run的值到工作内存后,因为 t1 线程要频繁从主内存中读取 run 的值,JIT 编译器会将 run 的值缓存至自己工作内存中的高速缓存中, 减少对主存中 run 的访问,提高效率

在1 秒之后, main 线程修改了 run 的值,并同步至主存,而 t1  是从自己工作内存中的高速缓存中读取这个变量的值,结果永远是旧值
当然,我们知道,只需要将run变量加上一个 volatile 就可以解决这个问题,然而,当我们在while循环中加入输出语句时,也可以跳出死循环,如图:
package logTest;

import lombok.extern.slf4j.Slf4j;

/**
 * @Author:wjy
 */
@Slf4j(topic = "c.test")
public class Test9_volitile {
    static boolean run = true;

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            while (run) {
                System.out.println(1);
            }
        });
        t1.start();

        Thread.sleep(1000);
        log.debug("停止 t");
        run = false;
    }
}

查看println的源码,可以看到:

println内部加了 synchronized 锁 也就是可重入锁加锁
在加锁时,将清空工作内存中的共享变量的值,从而使用共享变量时需要从主内存中重新读取最
新的值,因此,主线程中的 run值就会被读取,从而跳出循环
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值