网站建设的方案模板下载,如何应用网络营销发挥作用,东莞出租车公司,山东建设部网站文章目录优秀引用1、引入2、概述3、JMM内存模型的实现3.1、简介3.2、原子性3.3、可见性3.4、有序性4、相关面试题4.1、你知道什么是Java内存模型JMM吗#xff1f;4.2、JMM和volatile他们两个之间的关系是什么#xff1f;4.3、JMM有哪些特性/能说说JMM的三大特性吗#xff1f…
文章目录优秀引用1、引入2、概述3、JMM内存模型的实现3.1、简介3.2、原子性3.3、可见性3.4、有序性4、相关面试题4.1、你知道什么是Java内存模型JMM吗4.2、JMM和volatile他们两个之间的关系是什么4.3、JMM有哪些特性/能说说JMM的三大特性吗4.4、为什么要有JMM它为什么会出现作用和功能是什么4.5、有了解过happens-before原则吗优秀引用
全面理解Java的内存模型JMM
终于有人把Java内存模型(JMM)说清楚了
1、引入
对于Java虚拟机的内存模型相信大家都不陌生了对于每一个线程来说栈是私有的而堆是共享的也就是说在栈中的变量局部变量、方法定义参数、异常处理器参数不会在线程之间共享也就不会有内存可见性的问题也不受内存模型的影响。 既然堆中的数据是线程共享的那么一定会存在一个并发问题但由于每个线程都有自己的本地缓存导致线程之间读取的数据可能不是最新的从而出现数据不一致的问题。JMM定义了一种内存模型用于描述Java程序中多线程之间如何访问共享内存中的变量从而解决了这个问题。 这里扯一嘴在Java中使用的是共享内存并发模型用于解决Java中线程间如何通信和数据同步的问题。 2、概述
JMMJava Memory Model是Java内存模型的缩写是一种抽象的概念定义了Java虚拟机如何在计算机内存中存储和访问Java对象的方法。JMM规范主要用于解决多线程访问共享内存时的可见性、有序性和原子性问题。下面是JMM的抽象示意图 从上图中可以看出 所有的共享变量都存在主内存中 每个线程都保存了一份该线程使用到的共享变量的副本。 如果线程A与线程B之间要通信的话必须经历下面2个步骤 线程A将本地内存A中更新过的共享变量刷新到主内存中去。 线程B到主内存中去读取线程A之前已经更新过的共享变量。
因此线程A无法直接访问线程B的工作内存那是因为工作内存是线程独有的线程间通信必须借助主内存这也是JMM中的规定。当主内存中的共享变量被某个线程更新时JMM会通过控制主内存与每个线程的本地内存之间的交互来提供内存可见性保证。因此通过JMM规范有效的解决了以下问题
可见性问题JMM保证对于一个线程对变量的修改其他线程能够立即看到这个修改从而避免了线程之间读取数据不一致的问题有序性问题JMM保证程序的执行顺序是有序的即按照代码的编写顺序执行从而避免了出现代码执行顺序混乱的问题原子性问题JMM保证对单个变量的读取和写入操作是原子性的即不会出现数据竞争问题。
3、JMM内存模型的实现
3.1、简介
在Java中存在着许多并发相关的关键字如valatile、synchronized、final等而这些被大众所熟知的关键字便是Java内存模型封装了底层的实现后提供给开发人员进行使用。因此Java内存模型除了定义了一套规范还提供了一系列的封装了底层实现的关键字供开发者使用。
3.2、原子性
原子性指的是指一个操作是不可中断的即多线程环境下操作不能被其他线程干扰。在Java中最常用的便是使用关键字synchronized进行原子性的保证。
3.3、可见性
指当一个线程修改了某一个共享变量的值其他线程是否能够立即知道该变更。对于Java中的普通共享变量是不保证可见性的因为数据修改被写入内存的时机是不确定的多线程并发下很可能会出现脏读的并发问题因此便有着上面提及到的线程私有的工作内存。
每个线程的工作内存都保存了一份该线程使用到共享变量的副本即主内存中的拷贝副本在操作数据时只能在本地的副本中进行操作不能直接对主内存中的数据进行操作。同时不同线程间也是不能直接进行通讯的必须借助主内存来实现。
而在Java中提供了volatile、synchronized、final关键字来保证多线程操作时变量的可见性其中volatile关键字提供了这么一个功能那就是被其修饰的变量在被修改后可以立即同步到主内存中被其他修饰的变量在每次使用之前都从主内存中刷新获取从而保证可见性。
3.4、有序性
指程序是有序的按照一定的顺序运行这一特性主要是针对于操作系统中对程序指令进行重排序造成的并发乱序问题。为了性能和便捷在JMM中指明再不改变程序执行结果的前提下允许编译器和处理器对程序优化进行重排序。
在Java中可以使用synchronized和volatile来保证多线程之间操作的有序性。实现方式有所区别
volatile关键字会禁止指令重排synchronized关键字保证同一时刻只允许一条线程操作。
值得注意的是按照一定的顺序并不一定是代码中的顺序典型的例子便是线程的创建和执行下面的示例代码便是先执行第四行后执行第二行
Thread t1 new Thread(() - {System.out.println(hello thread);
}, t1);
t1.start();4、相关面试题
4.1、你知道什么是Java内存模型JMM吗
JMMJava内存模型是Java虚拟机规范中定义的一种内存模型用于描述Java程序中多线程之间如何访问共享内存中的变量。JMM规定了Java程序中的所有变量都存储在主内存中每个线程都有自己的本地缓存线程对变量的读取和写入操作都必须在本地缓存和主内存之间进行同步以保证数据的可见性、原子性和有序性。
JMM定义了一些规则和约束如volatile关键字、synchronized关键字等用于保证程序的正确性和稳定性。使用volatile关键字可以保证变量的可见性即每个线程都能看到其他线程对该变量的最新修改。使用synchronized关键字可以保证代码块的原子性即同一时刻只有一个线程能够执行该代码块。
4.2、JMM和volatile他们两个之间的关系是什么
volatile是对JMM底层实现封装的关键字之一是JMM的一种实现方式用于修饰变量表示该变量是可见性的即任何对该变量的修改都会立即被其他线程所看到。volatile关键字是JMM的一种实现方式它可以保证变量的可见性。
在Java中使用volatile关键字修饰的变量会被存储在主内存中每个线程访问该变量时都会从主内存中读取最新的值而不是从线程的本地缓存中读取。因此使用volatile关键字可以保证变量的可见性避免出现数据不一致的问题。
同时volatile关键字还具有禁止指令重排序的作用即保证代码的有序性。由于JMM规定了线程之间的操作可能会存在重排序的情况因此使用volatile关键字可以禁止指令重排序保证程序的正确性和稳定性。
4.3、JMM有哪些特性/能说说JMM的三大特性吗
JMMJava内存模型有三个特性也被称为JMM的三大特性分别是原子性、可见性和有序性。
原子性原子性是指对于单个变量的读取和写入操作是原子性的即不会出现数据竞争问题。在JMM中原子性是通过synchronized关键字和volatile关键字来保证的。可见性可见性是指当一个线程对一个变量进行修改时其他线程能够立即看到这个修改从而避免了线程之间读取数据不一致的问题。在JMM中可见性是通过volatile关键字来保证的。有序性有序性是指程序的执行顺序是有序的即按照代码的编写顺序执行从而避免了出现代码执行顺序混乱的问题。在JMM中有序性是通过happens-before规则来保证的。 happens-before规则定义了程序执行中各个操作之间的偏序关系主要述说的是某一段符合该规则的代码前面代码得到的结果肯定对后方代码是可见的。 4.4、为什么要有JMM它为什么会出现作用和功能是什么
在Java多线程编程中由于多个线程之间共享数据的情况很常见因此需要一种机制来保证多线程之间的数据访问是正确的。在JVM中由于每个线程都有自己的本地缓存因此线程之间读取的数据可能不是最新的从而出现数据不一致的问题。为了解决这个问题Java引入了JMM。
JMM的作用就是规定了一些规则保证多线程访问共享变量的正确性。JMM主要有以下几个功能
确定共享变量的可见性JMM规定如果一个线程修改了共享变量的值其他线程必须能够立即看到这个变化。确定操作的有序性JMM规定如果一个线程对共享变量进行了多次修改其他线程必须按照这些修改的顺序来看到这些变化。确定操作的原子性JMM规定如果一个线程在修改共享变量的过程中其他线程必须等待这个修改完成后再进行操作。
4.5、有了解过happens-before原则吗
happens-before原则是Java内存模型中一个重要的概念用于指定多线程程序中操作之间的顺序关系。
happens-before原则规定如果操作A happens-before操作B那么操作A的效果在操作B之前对其他线程是可见的。也就是说如果在一个线程中操作A happens-before操作B那么在另一个线程中看到操作A的效果一定是在看到操作B的效果之前。