zoukankan      html  css  js  c++  java
  • JMM内存模型

    java内存模型(Java Memory Module)

    虚拟机并不是直接操作主内存,而是又创建了一个缓存,类似cpu的高速缓存,要操作内存中的数据,一般会进行多步原子操作,这就会导致多个线程访问会出现一些问题。

    JMM的原子操作如下图说明

    volatile关键字

    /**
     * 循环里有代码,则会跳出循环,不知道什么原因
     */
    public class VolatileTest {
        private static  boolean flag = false; // 不适用volatile修饰,可能会进入死循环
        public static void main(String[] args){
            new Thread(()->{
                while (!flag){
                    ///System.out.println("flag已修改"); 循环里有代码,则会跳出循环,不知道什么原因
                }
                System.out.println("线程1停止");
            }).start();
    
            new Thread(()->{
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("修改flag的值");
                flag = true;
            }).start();
        }
    }
    

    并发编程三大特性:可见性,有序性,原子性。volatile能保证可见性和有序性,有两个主要作用,可见和禁止代码重排

    可见性:一个线程修改了某个共享变量的值,另一个线程可以感知到

    指令重排:在不影响单线程执行结果的情况下,计算机为了最大限度的利用cpu的性能,会对机器指令重排优化

    重排的原则:as-if-serial和happen-before

    volatile的实现原理:利用CPU的缓存一致性协议MESI,volatile马上将改变的变量写入主内存并开始MESI协议

    双重检测锁实现的单例,对象半初始化:由于指令重排的关系,可能会先执行对象闯将的init()方法,然后再执行putstatic,单线程没问题,但多线程会有问题

    class DoubleCheckInstance{
        private static DoubleCheckInstance instance = null;
        // 建议添加volatile关键字,避免代码重排
        // private static volatile DoubleCheckInstance instance = null;
    
        private DoubleCheckInstance(){}
        
        public static DoubleCheckInstance getInstance() {
            if(instance == null){// 如果a, b线程同时执行到这一步,符合判断,进入同步代码块
                synchronized (DoubleCheckInstance.class){
                    if(instance == null){ // 如果这里没有判断,则总是会执行new对象代码
                        instance = new DoubleCheckInstance();  // 创建对象有三个指令1. 分配对象的内存空间 2. 初始化对象 3. 设置instance指向刚分配的内存地址
                        // 可能会出现指令重排的情况,导致先执行3,在执行2,如果是单线程没有问题,多线程就会有问题
                    }
                }
            }
            return instance;
        }
    }
    

    https://blog.csdn.net/qq_37960603/article/details/103944203
    https://blog.csdn.net/DJYDFT2831djydft/article/details/113773631
    volatile关键字说明

    volatile保证有序性:使用内存屏障,JVM规范定义的内存屏障,可以保证指令的顺序

  • 相关阅读:
    毕业生的商业软件开发之路 C#语言简介
    [毕业生的商业软件开发之路]第一次使用VS.NET集成开发环境
    一种应用程序命令执行架构设计
    DCWriter 电子病历文档编辑器的 电子病历功能规范对照表
    [毕业生的商业软件开发之路]积累与创新
    WEB开发人员的微软技术战略
    PureMVC(AS3)剖析:吐槽
    走在网页游戏开发的路上(九)
    [服务器开发]可伸缩系统的设计模式(译)
    回合制页游
  • 原文地址:https://www.cnblogs.com/catelina/p/14474230.html
Copyright © 2011-2022 走看看