JAVA多线程编程——JAVA内存模型

一、何为“内存模型”

  内存模型描述了程序中各个变量(实例域、静态域和数组元素)之间的关系,以及在实际计算机系统中将变量存储到内存和从内存中取出变量这样的底层细节,对象最终是存储在内存里面的,但是编译器、运行库、处理器或者系统缓存可以有特权在变量指定内存位置存储或者取出变量的值。

二、JMM(Java Memory Model)即Java内存模型的作用

  1. JMM的最初目的是为了能够支持多线程程序。JMM使得每一个线程就像运行在不同的机器、不同的CPU或者本身就不同的线程上一样;
  2. JMM定义了Java语言针对内存的一系列相关规则。对于CPU本身而言,一个CPU不能直接访问其它CPU的寄存器,因此JMM必须通过某种定义规则来使得线程和线程在工作内存中进行相互调用,从而实现一个CPU对其它CPU、或者说一个线程对其它线程的内存中资源的访问;
  3. 虽然JMM设计之初是为了能够更好地支持多线程,但是JMM的应用和实现并不局限于多处理器,对于单CPU的系统而言,在JVM编译器编译Java程序的时候,以及运行时执行该程序的时候,这种规则也是有效的;
  4. JMM定义了线程与主存之间的抽象关系:每个线程可以被抽象为一块工作内存,程序中所有的共享变量都在主存中定义并存储,工作内存不能直接使用主存中的共享变量,如果要使用,工作内存必须对主存中的共享变量进行读取和拷贝,然后对拷贝过来的变量副本进行操作,最后将操作后的变量结果回写到主存中。大多数JMM规则在实现的时候,必须保证主存和工作内存之间进行通信,而且不能违反内存模型本身的结构。这是在设计语言的时候必须考虑到的针对内存的一种设计方法。

  作为Java程序员,我们需要知道的是,Java对内存的管理不需要人为操作,因为Java本身就拥有了一套自动的内存管理策略,这是Java相对与其它一些语言在进行内存管理上具备的一种优势。

三、线程间通信机制

  在命令式编程中,线程之间的通信机制有两种:共享内存和消息传递。

  1. 共享内存。线程之间共享程序的公共状态,线程之间通过写-读内存中的公共状态来隐式进行通信;
  2. 消息传递。线程之间没有公共状态,线程之间必须通过明确的发送消息来显式进行通信。

  Java在实现线程间通信时采用的是共享内存的方式,因而Java线程之间的通信总是隐式的,整个通信过程对程序员完全透明。如果我们在编写多线程程序的时候不理解这种隐式的通信机制,很可能会遇到各种奇怪的并发问题。

四、主存与工作内存

  上面我们将每个单独的线程抽象为一块工作内存,主存与线程之间的关系也就被抽象成了主存与工作内存的关系,这种关系用图可表示为:

  JMM定义了8中主存与工作内存之间的操作:

  1. lock(锁定):作用于主内存的变量,把一个变量标识为一条线程独占状态;
  2. unlock(解锁):作用于主内存变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定;
  3. read(读取):作用于主内存变量,把一个变量值从主内存传输到线程的工作内存中,以便随后的load动作使用;
  4. load(载入):作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中;
  5. use(使用):作用于工作内存的变量,把工作内存中的一个变量值传递给执行引擎,每当虚拟机遇到一个需要使用变量的值的字节码指令时将会执行这个操作;
  6. assign(赋值):作用于工作内存的变量,它把一个从执行引擎接收到的值赋值给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作;
  7. store(存储):作用于工作内存的变量,把工作内存中的一个变量的值传送到主内存中,以便随后的write的操作;
  8. write(写入):作用于主内存的变量,它把store操作从工作内存中一个变量的值传送到主内存的变量中。

  Java内存模型只要求上述操作必须按顺序执行,而没有保证必须是连续执行。也就是read和load之间,store和write之间是可以插入其他指令的,如对主内存中的变量a、b进行访问时,可能的顺序是read a,read b,load b, load a。

  JMM还规定了在执行上述八种基本操作时,必须满足如下规则:

  1. 不允许read和load、store和write操作之一单独出现;
  2. 不允许一个线程丢弃它的最近assign的操作,即变量在工作内存中改变了之后必须同步到主内存中;
  3. 不允许一个线程无原因地(没有发生过任何assign操作)把数据从工作内存同步回主内存中;
  4. 一个新的变量只能在主内存中诞生,不允许在工作内存中直接使用一个未被初始化(load或assign)的变量。即就是对一个变量实施use和store操作之前,必须先执行过了assign和load操作;
  5. 一个变量在同一时刻只允许一条线程对其进行lock操作,lock和unlock必须成对出现;
  6. 如果对一个变量执行lock操作,将会清空工作内存中此变量的值,在执行引擎使用这个变量前需要重新执行load或assign操作初始化变量的值;
  7. 如果一个变量事先没有被lock操作锁定,则不允许对它执行unlock操作;也不允许去unlock一个被其他线程锁定的变量;
  8. 对一个变量执行unlock操作之前,必须先把此变量同步到主内存中(执行store和write操作)。

五、关于重排序

  在Java程序的执行过程中,编译器和处理器会通过对指令进行重排序来优化程序的执行效率。重排序分为三种:

  1.编译器优化的重排序。编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序;

  2.指令级并行的重排序。现代处理器采用了指令级并行技术(Instruction-Level Parallelism, ILP)来将多条指令重叠执行。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序;

  3.内存系统的重排序。由于处理器使用缓存和读/写缓冲区,这使得加载和存储操作看上去可能是在乱序执行。

  从java源代码到最终实际执行的指令序列,会分别经历上面三种重排序。

获取【下载地址】  【免费支持更新】

三大数据库
mysql  oracle  sqlsever   更专业、更强悍、适合不同用户群体

【新录针对本系统的视频教程,手把手教开发一个模块,快速掌握本系统】

A 集成代码生成器 [正反双向(单表、主表、明细表、树形表,开发利器)+快速构建表单;
QQ:313596790

freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面、建表sql脚本,处理类,service等完整模块

B
集成阿里巴巴数据库连接池druid;

数据库连接池  阿里巴巴的 druid。Druid在监控、可扩展性、稳定性和性能方面都有明显的优势

C
集成安全权限框架shiro ;

Shiro 是一个用 Java 语言实现的框架,通过一个简单易用的 API 提供身份验证和授权,更安全,更可靠

D 集成ehcache 分布式缓存 ;

是一个纯Java的进程内缓存框架,具有快速、精干等特点,广泛使用的开源Java分布式缓存。

E 集成微信接口开发;    F 图片爬虫技术;   G  SQL 编辑器, 支持复杂sql语句,生成报表,可以导出excel;

H websocket及时通讯技术;(即时聊天、及时站内信并声音提醒、实时在线管理、websocket及时刷新页面);

?

时间: 2024-11-06 07:31:55

JAVA多线程编程——JAVA内存模型的相关文章

Java多线程中的内存模型

一:现代计算机的高速缓存 在计算机组成原理中讲到,现代计算机为了匹配 计算机存储设备的读写速度 与  处理器运算速度,在CPU和内存设备之间加入了一个名为Cache的高速缓存设备来作为缓冲:将运算需要用到的数据从内存复制到cache中,CPU可以在运算期间对cache进行高速的读写操作,运算结束后在从cache把数据同步回内存. Cache引出了一个新问题:缓存一致性.每个处理器有自己的cache,而他们又共享一个主内存.当多个处理器的运算任务都设计同一内存区域时,将会导致各自的缓存数据不一致.

Java - 32 Java 多线程编程

Java 多线程编程 Java给多线程编程提供了内置的支持.一个多线程程序包含两个或多个能并发运行的部分.程序的每一部分都称作一个线程,并且每个线程定义了一个独立的执行路径. 多线程是多任务的一种特别的形式.多线程比多任务需要更小的开销. 这里定义和线程相关的另一个术语:进程:一个进程包括由操作系统分配的内存空间,包含一个或多个线程.一个线程不能独立的存在,它必须是进程的一部分.一个进程一直运行,直到所有的非守候线程都结束运行后才能结束. 多线程能满足程序员编写非常有效率的程序来达到充分利用CP

Java多线程编程模式实战指南(二):Immutable Object模式--转载

本文由本人首次发布在infoq中文站上:http://www.infoq.com/cn/articles/java-multithreaded-programming-mode-immutable-object.转载请注明作者: 黄文海 出处:http://viscent.iteye.com. 多线程共享变量的情况下,为了保证数据一致性,往往需要对这些变量的访问进行加锁.而锁本身又会带来一些问题和开销.Immutable Object模式使得我们可以在不使用锁的情况下,既保证共享变量访问的线程安

Java多线程编程详解

线程的同步 由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题.Java语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被多个线程同时访问. 由于我们可以通过 private 关键字来保证数据对象只能被方法访问,所以我们只需针对方法提出一套机制,这套机制就是 synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块. 1. synchronized 方法:通过在方法声明中加入 synch

汪大神Java多线程编程实战

课程目录:├─1│  ├─Java并发编程.png│  ├─源码+ppt.rar│  ├─高并发编程第一阶段01讲.课程大纲及主要内容介绍.wmv│  ├─高并发编程第一阶段02讲.简单介绍什么是线程.wmv│  ├─高并发编程第一阶段03讲.创建并启动线程.mp4│  ├─高并发编程第一阶段04讲.线程生命周期以及start方法源码剖析.mp4│  ├─高并发编程第一阶段05讲.采用多线程方式模拟银行排队叫号.mp4│  ├─高并发编程第一阶段06讲.用Runnable接口将线程的逻辑执行单元

java多线程编程从入门到卓越(超详细总结)

导读:java多线程编程不太熟?或是听说过?或是想复习一下?找不到好的文章?别担心我给你们又安利一波,文章内容很全,并且考虑到很多开发中遇到的问题和解决方案.循环渐进,通俗易懂,文章较长,建议收藏再看! 往期精彩放送:一文搞定Java的输入输出流等常见流 一文搞定Java集合类,你还在为Java集合类而烦恼吗? 文章目录 1.多线程的概念 2.多线程并发 3.多线程程序设计 继承Thread类创建线程 新建类实现Runnable接口创建线程 改进(匿名内部类方式) 获取线程的名字和当前线程对象

java中JVM虚拟机内存模型详细说明

java中JVM虚拟机内存模型详细说明 2012-12-12 18:36:03|  分类: JAVA |  标签:java  jvm  堆内存  虚拟机  |举报|字号 订阅 JVM的内部结构如下图: 一个优秀Java程序员,必须了解Java内存模型.GC工作原理,以及如何优化GC的性能.与GC进行有限的交互,有一些应用程序对性能要求较高,例如嵌入式系统.实时系统等,只有全面提升内存的管理效率,才能提高整个应用程序的性能. 本文将从JVM内存模型.GC工作原理,以及GC的几个关键问题进行探讨,从

java多线程编程

一.多线程的优缺点 多线程的优点: 1)资源利用率更好2)程序设计在某些情况下更简单3)程序响应更快 多线程的代价: 1)设计更复杂虽然有一些多线程应用程序比单线程的应用程序要简单,但其他的一般都更复杂.在多线程访问共享数据的时候,这部分代码需要特别的注意.线程之间的交互往往非常复杂.不正确的线程同步产生的错误非常难以被发现,并且重现以修复. 2)上下文切换的开销当CPU从执行一个线程切换到执行另外一个线程的时候,它需要先存储当前线程的本地的数据,程序指针等,然后载入另一个线程的本地数据,程序指

Java多线程编程(学习笔记)

一.说明 周末抽空重新学习了下多线程,为了方便以后查阅,写下学习笔记. 有效利用多线程的关键是理解程序是并发执行而不是串行执行的.例如:程序中有两个子系统需要并发执行,这时候需要利用多线程编程. 通过多线程的使用,可以编写出非常高效的程序.但如果创建了太多的线程,程序执行的效率反而会降低. 同时上下文的切换开销也很重要,如果创建太多的线程,CPU花费在上下文的切换时间将对于执行程序的时间. 二.Java多线程编程 概念 在学习多线程时,我们应该首先明白另外一个概念. 进程:是计算机中的程序关于某