多线程之子线程死循环里加休眠或者加打印,会跳出死循环?问题记录待解决

问题描述:

  • 子线程死循环里加休眠,会跳出死循环,执行while后面的语句?
  • 子线程死循环里加打印,会跳出死循环,执行while后面的语句?

 

问题代码:

package com.demo;

import java.util.concurrent.TimeUnit;

/**
 * @Description
 * @Author by mocar小师兄
 * @Date 2020/3/13 16:54
 **/
public class Voletile_Thread {
    private static boolean Flag=false;
    private static int count=0;

    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "开始执行任务");
                while (!Flag) {
                    //子线程死循环里加休眠,会跳出死循环,执行while后面的语句?
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    count++;
                    //子线程死循环里加打印,会跳出死循环,执行while后面的语句?
                    System.out.println("count:\t" + count);
                }
                System.out.println( Thread.currentThread().getName() +"执行结束");
            }
        });
        thread1.start();
        System.out.println("Main主线程等待1秒");
        Thread.sleep(200);
        Flag=true;
        System.out.println("Main主线程修改了Flag值,主线程结束");

    }
}

 

 

 

 

当注释掉休眠和打印的语句,子线程可以正常死循环!

package com.demo;

import java.util.concurrent.TimeUnit;

/**
 * @Description
 * @Author by mocar小师兄
 * @Date 2020/3/13 16:54
 **/
public class Voletile_Thread {
    private static boolean Flag=false;
    private static int count=0;

    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "开始执行任务");
                while (!Flag) {
                    //子线程死循环里加休眠,会跳出死循环,执行while后面的语句?
                    /*try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }*/
                    count++;
                    //子线程死循环里加打印,会跳出死循环,执行while后面的语句?
                    //System.out.println("count:\t" + count);
                }
                System.out.println( Thread.currentThread().getName() +"执行结束");
            }
        });
        thread1.start();
        System.out.println("Main主线程等待1秒");
        Thread.sleep(200);
        Flag=true;
        System.out.println("Main主线程修改了Flag值,主线程结束");

    }
}

 

 

解释:

为什么子线程死循环里加打印/休眠,会跳出死循环?

1、先说下多线程下的内存模型

对非 volatile 变量进行读写的时候,每个线程先从内存拷贝变量到CPU缓存中。如果计算机有多个CPU,每个线程可能在不同的CPU上被处理,这意味着每个线程可以拷贝到不同的 CPU cache 中。

 

2、

先解释正常情况下,子线程中不加 sleep 和  System.out.println("count:\t" + count),如下:

        一开始主线程中的Flag的变量值为false,创建了一个子线程Thread-0,将Flag复制到运行内存中,因为Thread-0在运行的时候Flag一直都是false,因此while循环会一直运行。虽然后面主线程休眠了一小会后,改变了主内存里面Flag为true了,但是影响不了Thread-0运行内存中的Flag的值。因此Thread-0会一直在while中无限循环。

        现在加了println后,因为println操作是Synchronized加锁的,它会做以下的操作:

  • 1、获得同步锁;
  • 2、清空工作流出来;
  • 3、从主内存拷贝对象副本到线程工作内存中;
  • 4、开始继续执行代码
  • 5、刷新主内存数据
  • 6、释放同步锁。

System.out.println源码如下:

在清空内存刷新内存的过程中,Thread-0线程有这么一个操作:获取锁到释放锁。Thread-0线程的Flag就变成了true(从主内存拷贝对象副本到线程工作内存中),所以就跳出了循环。指令重排序的情况也就不会出现了,这也是Volatile关键字的两种特性之一。

子线程中加休眠也是一个道理,调用sleep()时,线程虽然休眠了,但是对象的机锁没有被释放。当锁释放后,又会从从主内存拷贝对象副本到线程工作内存中。

 

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值