说到Java内存模型可能一开始就会让人想到Java虚拟机里面的数据区的概念,但是这里的Java内存模型(JMM,Java memory model)是指用Java语言规范定义的内存模型,它是用在线程间数据的可见性上的定义,在Java中数据会存在所见非所得的情况,也就是说你在程序上面看上去会得到想要的结果,但是现实是运行出来的结果往往并不是自己想要的,如下的一个例子(直接敲的代码可能不正确,大概意思是这样)
public class TestSee{ boolean canSee = true; public static void main(String [] args){ TestSee testSee = new TestSee(); new Thread(() -> { int i = 0; while(testSee.canSee){ i++; } System.out.println(i); }).start(); Thread.sleep(3000); testSee.canSee = false; } }
这个通过启动一个子线程来判断canSee为true的时候一直运行,然后整个主线程休眠3秒过后,将canSee赋值为了false,我们想要的效果就是在改为false后子线程也退出了程序的运行,但是在不同的参数情况下子线程有可能是没有办法退出的,是因为它可能并不知道canSee已经修改为false,造成这个的原因可能是高速缓存引起的,为什么会是高速缓存呢?这个就需要去了解下Java的解释执行和编译执行了,当Java运行一定时间的解释执行时因为程序没有任何变化,为了更好的节约内存资源,就会通过指令重排的方式通过JIT(just in time complier)的方式进行编译执行,将代码进行缓存起来,也会就会出现下面这样的伪代码
boolean see = canSee; while(true){ i++; }
所以后面不管canSee是否改变了有可能都不能得到正确的响应了。
那么我们可以通过什么方式来防止缓存呢?答案就是使用volatile关键字了,使用了这个关键字后虚拟机就会自动禁用高速缓存和指令重排了,如果改变了使用volatile关键字修饰的变量,在很短暂的时间会通过Java将变量的工作线程和主线程的修改值进行传递来及时的响应值的变化,从而达到线程间数据可见性的,同时通过volatile关键字修饰的变量会有以下几个特征:
1.变量的修改会对后面所有的其他线程可见
2.如果变量的修改A动作发生在动作B之前,动作B又发生在动作C之前,那么变量的修改A动作也会对C动作产生可见性
3.如果线程t1成功执行了线程t2.join()方法,那么t1的所有操作对t2都可见
上面的这些特征也叫做happen-before原则,因此如果对于一个公共变量来说,如果需要经常修改而又有其他线程对其引用,最好就使用volatile关键字进行修饰。
对于数据的可见性同步保证除了使用volatile关键字以外,还有以下几种情形:
1.使用加锁/解锁进行控制,它不会产生指令重排
2.线程启动时和该线程中的第一个执行的命令也一定是同步保证的
3.子线程的最后操作与主线程是同步保证的
4.如果在主线程中通过interrupt方式中断了子线程的执行,那么这中断操作也会对其他子线程可见,当然这里也并不一定是主线程执行中断操作,只有其他子线程可以使用到中断子线程的实例都可以执行中断操作。
在使用的过程中对应不变的变量最好使用final来修饰,保证对所有线程的可见及不可修改,同时最好不要修改共享的byte[]数组,这个会带来数据一致性的问题,volatile关键字对64位的共享值(double,long)也更好一些。
相关推荐
### Java内存模型详解 #### 1. JMM简介 ##### i. 内存模型概述 Java内存模型(Java Memory Model, JMM)是Java虚拟机(JVM)的一部分,用于规定程序中的各种变量(包括实例字段、静态字段和数组元素等)在多个...
Java内存模型(JMM)是Java虚拟机(JVM)规范的一部分,用于定义多线程环境下共享变量的访问规则和操作的可见性。本文将对Java内存模型进行知识汇总,帮助读者更好地理解和掌握相关知识点。 首先,内存模型的概念是...
### Java内存模型详解 #### 一、JMM简介 ##### 1. 内存模型概述 Java内存模型(Java Memory Model, JMM)是Java虚拟机(JVM)的一部分,它规定了程序中各种变量(包括实例字段、静态字段和数组元素)的访问规则,...
Java内存模型,简称JMM(Java Memory Model),是Java虚拟机规范中定义的一个抽象概念,它描述了在多线程环境下,如何在共享内存中读写变量,以及这些读写操作的可见性、原子性和有序性。这个模型规定了线程与主内存...
### Java 虚拟机JVM内存模型知识点 #### 1. JVM概述 ##### 1.1 Java的特性与JVM的应用 Java语言的特性包括跨平台性、面向对象、安全性等。JVM是Java程序能够跨平台运行的关键,它负责将Java源代码转换成与平台无关...
本文将详细介绍Java内存模型的基本概念、其重要特性和如何通过实际代码来确保并发环境下的程序正确性。 ## Java内存模型概述 Java内存模型规定了所有线程对共享变量的操作(包括读取和写入)都必须通过主内存来...
### Java内存模型与内存结构详解 #### 一、引言 在深入了解Java内存模型与内存结构之前,我们首先需要明确这两个概念的区别与联系。简单来说,“内存结构”侧重于描述虚拟机执行Java程序时如何组织内存空间;而...
本文将深入探讨`concurrentMap`在Java内存模型(JMM,Java Memory Model)中的实现原理,以及如何通过HotCode优化并发性能。 Java内存模型定义了线程之间的共享变量访问规则,确保在多线程环境下正确地同步数据。...
Java内存模型(Java Memory Model, JMM)定义了一组规则,用于规范程序执行中的内存一致性,包括对变量读写的原子性、可见性和有序性的规定。JMM的设计旨在解决多线程环境下的数据一致性问题。 ##### 1. 主内存与...
本文将深入探讨Java中堆内存与栈内存的分配机制,并通过对比分析它们之间的差异,帮助读者更好地掌握Java内存管理的核心概念。 #### 二、堆内存与栈内存概述 ##### 1. 堆内存 堆内存是Java虚拟机(JVM)用于存储...
Java内存模型与并发技术是Java开发中的核心概念,它们直接影响着多线程程序的正确性和性能。本讲座主要探讨了Java内存模型(JMM)的基础理论以及并发编程的关键点。 首先,内存模型是一个抽象的概念,它描述了一个...
为了应对这些问题,C++09引入了一个全新的内存模型,该模型基于Java的内存模型,并进行了适当的调整以适应C++的特性。具体来说,C++09内存模型具有以下几个特点: 1. **显式的内存操作语义**:C++09定义了一套标准...
为了理解多线程Java程序在多处理器上的行为,我们需要正式理解硬件内存模型(如SPARC的TSO/PSO模型)以及软件内存模型(JMM)。通过正式的可执行规范,我们可以计算测试程序在JMM和硬件内存模型下的所有允许行为,...
近期,在诚信通开源研究小组的专题学习分享会上,我们针对Java内存模型(JMM)进行了深入探讨,现将JMM相关的一些核心概念进行梳理,以便更好地理解和把握JMM的基本原理。 #### 第一问:JMM是干什么的? JMM (Java ...
在这个主题中,我们将深入探讨Java内存的几个关键方面,包括Java内存模型、垃圾收集机制、内存泄漏以及优化策略。以下是对这些知识点的详细阐述: 1. **Java内存模型(JMM)**: Java内存模型定义了线程之间如何...
首先,我们要理解Java内存模型的基础。Java内存主要分为堆内存(Heap)和栈内存(Stack)。堆内存用于存储对象实例,而栈内存则用于存储方法调用时的局部变量和方法参数。除此之外,还有方法区(Method Area)、程序...
在处理Java内存问题时,理解JVM的内存模型也是至关重要的。Java内存分为堆(Heap)、方法区(Method Area)、栈(Stack)、本地方法栈(Native Method Stack)和程序计数器(PC Register)五大部分。HeapAnalyzer...