`
357029540
  • 浏览: 725505 次
  • 性别: Icon_minigender_1
  • 来自: 重庆
社区版块
存档分类
最新评论

Java内存模型简单介绍

    博客分类:
  • JAVA
阅读更多

         说到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)也更好一些。

     

 

0
0
分享到:
评论

相关推荐

    传智播客_Java基础_Java内存结构

    但是初学者往往深陷Java语言的内存存储结构模型,大量复杂的设计模型使其很难对所学知识进行融会贯通。李若亮老师带你深入剖析Java编程中所内存涉及的方方面面,从JVM的内存申请,到Java语言的内存加载以及Java语言...

    Java线程/内存模型的缺陷和增强

     一、Java内存模型 在了解Java的同步秘密之前,先来看看JMM(JavaMemoryModel)。 Java被设计为跨平台的语言,在内存管理上,显然也要有一个统一的模型。而且Java语言最大的特点就是废除了指针,把

    jvm详细内存模型图1

    查看《深入理解Java虚拟机》后,自己简单总结的jvm相关的简单模型图。

    joeylv#joscrapy#【死磕Java并发】—–Java内存模型之重排序1

    下面我们用一个简单的示例来说明:A、B、C三个操作存在如下关系:A、B不存在数据依赖关系,A和C、B和C存在数据依赖关系,因此在进行重排序的时候,A、B可以随意

    Java理论与实践:修复Java内存模型,第1部分

    活跃了将近三年的JSR133,近期发布了关于如何修复Java内存模型(JavaMemoryModel,JMM)的公开建议。原始JMM中有几个严重缺陷,这导致了一些难度高得惊人的概念语义,这些概念原来被认为很简单,如volatile、final...

    Java高并发实战_java高并发_高并发_

    介绍了两个重要的并行性能评估定律, 以及 Java 内存模型 JMM。第2章介绍了 Java 并行程序开发的基础, 包括 Java 中 Thread 的基本使用方法等第3章介绍了 JDK 内部对并行程序开发的支持, 主要介绍 JUC (Java.util....

    浅谈Java内存模型之happens-before

    于存在线程本地内存和主内存的原因,再加上重排序,会导致多线程环境下存在可见性的问题。那么我们正确使用同步、锁的情况下,线程A修改了变量a何时对线程B可见?下面小编来简单介绍下

    JVM内存管理_GC模型_编写GC友好的代码

    JVM内存管理的介绍,编写GC友好的代码。 本材料主要关心 Sun Hotspot JVM 6的内存管理 Sun Hotspot JVM 6的GC模型 主要针对JVM6的GC模型,但也会简单介绍Java 7的G1 编写GC友好代码的一些技巧

    JVM内存模型一些简单的概述

    一、JVM内存模型概述 ........................ ........................ 二、程序计数器 ........................ ........................ 三、虚拟机栈 ........................ ........................ 四...

    java源码包---java 源码 大量 实例

     基于JAVA的UDP服务器模型源代码,内含UDP服务器端模型和UDP客户端模型两个小程序,向JAVA初学者演示UDP C/S结构的原理。 简单聊天软件CS模式 2个目标文件 一个简单的CS模式的聊天软件,用socket实现,比较简单。 ...

    java虚拟机知识点整理

    高效并发-java内存模型与线程 线程安全与锁优化 1 标记-清除算法:首先标记所有需要回收的对象(引用计数或可达性分析算法标记),在标记完成后统一回收所有被标记的对象。 缺点:效率问题,标记和清除两个过程效率都...

    基于java NIO的简单聊天软件示例

    NIO是一种基于通道和缓冲区的I/O方式,它可以使用Native函数库直接分配堆外内存(区别于JVM的运行时数据区),然后通过一个存储在java堆里面的DirectByteBuffer对象作为这块内存的直接引用进行操作。这样能在一些...

    Java开发技术大全(500个源代码).

    示例描述:本章介绍开发Java的基础语法知识。 accumulationByDoWhile.java 用do~while语句写的累加程序 accumulationByFor.java 用for语句写的累加程序 accumulationByWhile.java 用while语句写的累加程序 ...

    JAVA上百实例源码以及开源项目

     基于JAVA的UDP服务器模型源代码,内含UDP服务器端模型和UDP客户端模型两个小程序,向JAVA初学者演示UDP C/S结构的原理。 简单聊天软件CS模式 2个目标文件 一个简单的CS模式的聊天软件,用socket实现,比较简单。 ...

    JAVA上百实例源码以及开源项目源代码

     基于JAVA的UDP服务器模型源代码,内含UDP服务器端模型和UDP客户端模型两个小程序,向JAVA初学者演示UDP C/S结构的原理。 简单聊天软件CS模式 2个目标文件 一个简单的CS模式的聊天软件,用socket实现,比较简单。 ...

    JAVA多线程编程详解-详细操作例子

    具体到java内存模型,由于Java被设计为跨平台的语言,在内存管理上,显然也要有一个统一的模型。系统存在一个主内存(Main Memory), Java中所有变量都储存在主存中,对于所有线程都是共享的。每条线程都有自己的...

    java源码包4

     基于JAVA的UDP服务器模型源代码,内含UDP服务器端模型和UDP客户端模型两个小程序,向JAVA初学者演示UDP C/S结构的原理。 简单聊天软件CS模式 2个目标文件 一个简单的CS模式的聊天软件,用socket实现,比较简单。 ...

Global site tag (gtag.js) - Google Analytics