第五阶段(三)线程通信 线程状态 线程不可见性

线程通信

线程通信的三种方法:

(1)wait:当前线程释放锁,进入等待状态

(2)notify:当前锁释放,唤醒其它线程对当前资源进行获取

(3)notifyAll:唤醒所有线程

——如果只是wait不去进行notify,该线程资源就会一直进行等待

线程状态

 public static void main(String[] args) {

        //新建状态,只是线程对象,没有线程特征
        Thread.State aNew = Thread.State.NEW;

        //可运行状态 - 运行结果便是剩余的四种状态
        Thread.State runnable = Thread.State.RUNNABLE;

        //被阻塞状态 - 没有获取到锁 - 还在排队中
        Thread.State blocked = Thread.State.BLOCKED;

        //sleep或者waiting对应时间,进入计时等待 - 其中sleep时候锁未释放,而waiting的时候锁已经释放
        Thread.State timedWaiting = Thread.State.TIMED_WAITING;

        //直接进入wait等待,未进行notify则会一直wait
        Thread.State waiting = Thread.State.WAITING;

        //终止状态 - 线程运行完毕
        Thread.State terminated = Thread.State.TERMINATED;

    }

线程不可见行

1、首先去进行场景引入吧

public class VolatileDem_one extends Thread {

    private boolean flag = false;

    @Override
    public void run() {
        try {
            Thread.sleep(1100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("子线程对flag进行修改,且修改为true");
        flag = true;
    }

    public static void main(String[] args) {
        VolatileDem_one volatileDem_one = new VolatileDem_one();
        volatileDem_one.start();
        while (true) {
            //此时这段已经执行完成,子线程对其进行修改,但未知会到主线程 —— 进程间不可知性 - 一直在读取
            if (volatileDem_one.flag) {
                System.out.println("flag已修改");
            }
        }

    }
}

主线程会提示flag已修改吗?不会的,子线程的修改在自己的工作空间内,主线程不会主动的去从子线程种获取该对象,除非中间有对应的机制进行同步操作——这个就是线程间变量的不可见性,不可见性的具体原因有以下几点:

*  每个线程都有自己的工作内存,线程都是从主内存拷贝共享变量的副本值
*  每个线程是在自己的工作内存中操作共享变量的

 2、如何保证线程变量之间的可知性?这块有两种方式

(1)获取该资源的时候进行加锁,加锁之前会先对工作空间内存进行清空,从主内存中去获取动态变化的值,变化之后的资源便会同步到自己的工作空间中,在锁释放后,本身的变更也会同步到主线程中——是一种被动的方式

public class VolatileDem_two extends Thread {
    
    private boolean flag = false;
    @Override
    public void run() {
        try {
            Thread.sleep(1100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("子线程对flag进行修改,且修改为true");
        flag = true;
    }

    public static void main(String[] args) {
        VolatileDem_two volatileDem_two = new VolatileDem_two();
        volatileDem_two.start();
        while (true) {
            //此时这段已经执行完成,子线程对其进行修改,但未知会到主线程 —— 进程间不可知性 - 一直在读取
            synchronized (VolatileDem_two.class) {
                if (volatileDem_two.flag) {
                    System.out.println("flag已修改");
                }
            }
        }
    }
    
}

(2)使用volatile关键字对变量进行修改

当volatile修饰的变量发生修改时,主内存中对应的变量的值也会同步发生修改,主内存会向使用该变量的线程发送资源变更事件,其它线程回去主动从主内存空间中去进行读值——相对于锁,这是一种主动的方式

public class VolatileDem_three extends Thread {
    
    private volatile boolean flag = false;

    @Override
    public void run() {
        try {
            Thread.sleep(1100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("子线程对flag进行修改,且修改为true");
        flag = true;
    }

    public static void main(String[] args) {
        VolatileDem_three volatileDem_three = new VolatileDem_three();
        volatileDem_three.start();
        while (true) {
            //此时这段已经执行完成,子线程对其进行修改,但未知会到主线程 —— 进程间不可知性 - 一直在读取
            if (volatileDem_three.flag) {
                System.out.println("flag已修改");
            }
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值