笨蛋学JUC并发编程-共享模型之内存

3.1Java内存模型

JMM 即 Java Memory Model,它定义了主存(所有线程都共享的数据,可以认为对应着物理内存)、工作内存(每个线程私有的数据,可以认为对应着缓存)抽象概念,底层对应着 CPU 寄存器、缓存、硬件内存、CPU 指令优化等。

JMM 体现在以下几个方面

  • 原子性 - 保证指令不会受到线程上下文切换的影响
  • 可见性 - 保证指令不会受 cpu 缓存的影响
  • 有序性 - 保证指令不会受 cpu 指令并行优化的影响

3.2可见性

3.2.1退不出的循环

main 线程对 run 变量的修改对于 t 线程不可见,导致了 t 线程无法停止:

static boolean run = true;

public static void main(String[] args) throws InterruptedException {
   
    
    Thread t = new Thread(()->{
   
        while(run){
   
            // ....
        }
    });
    t.start();
    
    sleep(1);
    run = false; // 线程t不会如预想的停下来
}

3.2.2分析

  1. 初始状态, t 线程刚开始从主内存读取了 run 的值到工作内存。

    在这里插入图片描述

  2. 因为 t 线程要频繁从主内存中读取 run 的值,JIT 编译器会将 run 的值缓存至自己工作内存中的高速缓存中,减少对主存中 run 的访问,提高效率

    在这里插入图片描述

  3. 1 秒之后,main 线程修改了 run 的值,并同步至主存,而 t 是从自己工作内存中的高速缓存中读取这个变量的值,结果永远是旧值

    在这里插入图片描述

3.2.3解决方法

  • volatile(易变关键字)

    • 可以用来修饰成员变量和静态成员变量

    • 可以避免线程从自己的工作缓存中查找变量的值,必须到主存中获取它的值,线程操作 volatile 变量都是直接操作主存

    volatile static boolean run = true;
    
  • synchronized

    • 通过加锁同一对象来解决变量变动的问题
    • synchronized 语句块既可以保证代码块的原子性,也同时保证代码块内变量的可见性。
    • 但缺点是synchronized 是属于重量级操作,性能相对更低
        static boolean run = true;
        static Object lock=new Object();
        public static void main(String[] args) throws InterruptedException {
         
    
            Thread t = new Thread(()->{
         
                while(true){
         
                    synchronized (lock){
         
                        if(!run) break;
                    }
                }
            });
            t.start();
    
            sleep(1);
            //因为加锁的是同一对象
            synchronized (lock) {
         
                // 线程t如预想的停下来
                run = false;
            }
             
        }
    

3.2.4原子性和可见性

volatile关键字体现的实际就是可见性

  • 它保证的是在多个线程之间,一个线程对 volatile 变量的修改对另一个线程可见,不能保证原子性,仅用在一个写线程,多个读线程的情况

3.2.5两阶段终止模式

private Thread thread;
    private volatile boolean stop = false;

    public void start(){
   
        thread = new Thread(() -> {
   
            while(true) {
   
                if(stop) {
   
                    log.debug("料理后事");
                    break;
                }
                try {
   
                    Thread.sleep(1000);
                    log.debug("将结果保存");
                } catch (InterruptedException e) {
   

                }
                // 执行监控操作
            }
        },"监控线程");
        thread.start();
    }

    public void stop() {
   
        stop = true;
        //当if判断完,就不再执行sleep方法
        thread.interrupt();
    }

3.2.6同步模式之Balking

//判断是否执行过start方法
    private volatile 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值