一、硬件与效率的一致性

  计算机的存储设备与处理器的运算速度存在几个数量级的差距,现在计算机系统不得不在内存和处理器之间增加一层高速缓存(cache)来作为缓冲。将运算需要的数据复制到缓存中,让运算能够快速进行,当运算结束的时候再讲数据从缓存同步到内存中,这样处理器无须等待缓慢的内存读写。除了增加高速缓存外,为了使处理器的内存的运算单元能被充分的利用,处理器可能对输入的代码进行乱序执行优化,即常说的重排序,计算后对乱序执行的结果重组,保证结果与顺序执行代码的结果一致,但是并不保证各个语句的计算顺序与代码顺序一致。

  基于高速缓存的存储交互很好的解决了处理器与内存的速度矛盾,引进了一个新的问题:缓存一致性。在多处理器计算机系统中,每个处理器都有自己的高速缓存,而它们又共享同一主内存,当处理器的运算任务涉及到同一块主内存区域的时候,很可能导致各自的缓存数据不一致。解决这个问题,需要各个处理器访问缓存的时候遵循一些协议,在读写时根据协议来进行操作。

二、java内存模型

  内存模型可以理解为在特定的操作协议下,对特定的内存或高速缓存进行读写访问的过程抽象,不同架构的物理机器可以拥有不一样的内存模型,而java虚拟机有自己的内存模型。同样的,java虚拟机的即时编译器中有类似的指令重排序优化功能。java虚拟机规范中定义的内存模型用来屏蔽掉各种硬件环境和操作系统的内存访问差异,以实现让java程序在各个平台都能达到一致的内存访问效果。在jdk1.5发布后,java的内存模型已经成熟和完善起来。

  java内存模型的主要目标是为了定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量的底层细节。这里的变量与java语言中说的变量不是同一个东西,包括:实例字段,静态变量和构成数组对象的元素,但是不包括局部变量和方法参数(线程私有,不会共享,自然不存竞争问题)。java内存模型不限制执行引擎使用处理器的寄存器或缓存来和主内存进行交互,不限制即时编译器进行重排序优化。java内存模型的规范如下:

1.主内存与工作内存

Java内存模型规定
.所有的变量都存储在主内存(虚拟机内存的一部分)。
.每条线程有自己的工作内存,线程的工作内存保存了被该线程使用到的变量的主内存副本拷贝,线程对变量的读取,赋值等必须在工作内存中进行。
.不同线程之间无法直接访问对方工作内存中的变量,线程间的变量值传递需要借助主内存完成。

2.java内存间的交互操作

内存交互:即一个变量如何从主内存拷贝到工作内存,又如何从工作内存同步到主内存之类的实现细节。Java内存模型定义八种操作来完成,并且下面八种操作都是原子的,不可再分的。如下:

lock(锁定):作用于主内存中的变量,它把变量标识为一条线程独占的状态。

unlock(解锁):作用主内存中的变量,它把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。

read(读取):作用于主内存中的变量,把一个变量从主内存传输到线程的工作内存中,以便随后的load操作。

load(载入):作用于工作内存中的变量,把read操作从主内存中得到的变量放入工作内存的变量副本中。

use(使用):作用于工作内存的变量,把一个工作内存中的变量的值传递给执行引擎,每当虚拟机遇到一个需要使用到变量的值得字节码指令的时候将会执行这个操作。

assign(赋值):作用工作内存的变量,把从执行引擎接收到的值付赋给工作内存中的变量。

store(存储):作用于工作内存中的变量,把工作内存中的一个变量的值传递到主内存中,以便后续的write操作。

write(写入):作用于主内存中的变量,把store操作得到的变量的写入到主内存中对应的变量中。

注意:java内存模型要求read和load操作顺序执行,同时要求store和write操作顺序执行。

3.volatile变量的特殊规则

  • 保证volatile变量对所有线程的可见性,与普通变量的区别保证变量的新值能立即同步到主内存,以及每次使用的时候立即从主内存刷新。
  • volatile变量禁止指令重排序优化(主要通过内存屏障指令来实现)

内存屏障:指重排序的时候,不能把后面的指令重排序到内存屏障之前的位置。

4.long和doubel型变量的特殊规则

允许虚拟机将没被volatile修饰的64位数据的读写划分为两次32位的操作来进行。如long和double变量。但是目前商用虚拟机几乎把64数据的读写操作作为原子操作来对待。

5.原子性、可见性和有序性

原子性:即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。原子代表不可分割性。基本数据类型的访问读写具备原子性。synchronized块之间的操作具备原子性。

可见性:当一个线程修改共享变量的值,其他线程能够立即知道这个修改。java中volatile,synchronized和final能够实现变量的可见性。

有序性:线程内表现为串行语义,指令重排序和工作内存与主内存同步延迟的现象导致在其他线程观察另外一个线程,其操作都是无序的。java提供volatile和synchronized两个关键字来保证线程之间操作的有序性。

5.先行发生原则

java语言中有一个先行发生的原则,即happen-before,是判断是否存在竞争和线程是否安全的主要依据。java内存模型规定天然先行发生关系:

  • 程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作;
  • 锁定规则:一个unLock操作先行发生于后面对同一个锁额lock操作;
  • volatile变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作;
  • 线程启动规则:Thread对象的start()方法先行发生于此线程的每个一个动作;
  • 线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生;
  • 线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行;
  • 对象终结规则:一个对象的初始化完成先行发生于他的finalize()方法的开始;
  • 传递规则:如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于操作C;

三、java线程在虚拟机中的实现

  线程是比进程更轻量级的调度执行单位,线程的引入,可以把一个进程的资源分配和调度分开,各个线程可以共享进程资源,又可以独立调度(线程是CPU调度的基本单位)。主流的操作系统都提供了线程实现,Java语言则提供在不同硬件和操作系统平台下对线程的统一处理。每个执行了start()且还未结束的java.lang.Thread类的实例就代表一个线程。

1.Java线程的实现

Java线程模型在jdk1.2后是基于操作系统原生线程模型来实现的,因此操作系统支持怎样的线程模型,在很大程度上决定了Java虚拟机的线程是怎样映射的。对于sun JDK来说,它在windows和linux都是使用一对一的线程模型实现,即一条java线程映射到一条轻量级进程之中。

2.Java线程调度

线程调度:系统为线程分配处理器使用权的过程。主要两种方式:协同式线程调度和抢占式线程调度。java线程调度取决于操作系统的线程调度模式。

3.线程状态转换

java语言定义五种线程状态,任意一个时间点,一个线程只能有且只有其中一种状态,五种状态如下:

. 新建状态(New)         : 线程对象被创建后,就进入了新建状态。例如,Thread thread = new Thread()。
. 就绪状态(Runnable): 也被称为“可执行状态”。线程对象被创建后,其它线程调用了该对象的start()方法,从而来启动该线程。例如,thread.start()。处于就绪状态的线程,随时可能被CPU调度执行。
. 运行状态(Running) : 线程获取CPU权限进行执行。需要注意的是,线程只能从就绪状态进入到运行状态。
. 阻塞状态(Blocked) : 阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
() 等待阻塞 -- 通过调用线程的wait()方法,让线程等待某工作的完成。
() 同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态。
() 其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
. 结束状态(Terminated): 线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

线程状态转换关系如下:

JVM--内存模型与线程的更多相关文章

  1. 漫谈 JVM —— 内存模型、线程、锁

    Java 内存模型(JMM),实际上的目的就是为了统一内存管理.这让我想到了,作为一个程序员总是想着有银弹,有一个代码能万能的在所有场景上.经过多次尝试我发现这是不可能的:需求在变,技术在更新,没有什 ...

  2. 从linux进程角度看JVM内存模型

    普通进程栈区,在JVM一般仅仅用做线程栈,如下图所示 首先是永久代.永久代本质上是Java程序的代码区和数据区.Java程序中类(class),会被加载到整个区域的不同数据结构中去,包括常量池.域.方 ...

  3. jvm(12)-java内存模型与线程

    [0]README 0.1)本文部分文字描述转自“深入理解jvm”,旨在学习“java内存模型与线程” 的基础知识:   [1]概述 1)并发处理的广泛应用是使得 Amdahl 定律代替摩尔定律称为计 ...

  4. JVM内存模型、指令重排、内存屏障概念解析

    在高并发模型中,无是面对物理机SMP系统模型,还是面对像JVM的虚拟机多线程并发内存模型,指令重排(编译器.运行时)和内存屏障都是非常重要的概念,因此,搞清楚这些概念和原理很重要.否则,你很难搞清楚哪 ...

  5. JVM内存模型和性能优化 转

    JVM内存模型和性能优化 JVM内存模型优点 内置基于内存的并发模型:      多线程机制 同步锁Synchronization 大量线程安全型库包支持 基于内存的并发机制,粒度灵活控制,灵活度高于 ...

  6. JVM内存模型和性能优化

    JVM内存模型优点 内置基于内存的并发模型:      多线程机制 同步锁Synchronization 大量线程安全型库包支持 基于内存的并发机制,粒度灵活控制,灵活度高于数据库锁. 多核并行计算模 ...

  7. JVM初探 -JVM内存模型

    JVM初探 -JVM内存模型 标签 : JVM JVM是每个Java开发每天都会接触到的东西, 其相关知识也应该是每个人都要深入了解的. 但接触了很多人发现: 或了解片面或知识体系陈旧. 因此最近抽时 ...

  8. JVM内存模型和关键参数设置

    一. JVM内存模型: Jvm内存模型是学好Java很重要的一部分,该部分学习能让我们在系统运维的时候,或者优化服务器的时候能够有方法,懂原理. 二. Jvm关键参数: 1. 堆大小设置参数: -Xm ...

  9. 记录JVM内存模型,参数含义和优化

    一.JVM内存模型 (图片来自网络) 根据Java虚拟机规范,JVM将内存划分为: New(年轻代) Tenured(年老代) Perm (永久代) 其中New和Tenured属于堆内存,堆内存会从J ...

  10. jvm内存模型和内存分配

    1.什么是jvm? (1)jvm是一种用于计算设备的规范,它是一个虚构出来的机器,是通过在实际的计算机上仿真模拟各种功能实现的. (2)jvm包含一套字节码指令集,一组寄存器,一个栈,一个垃圾回收堆和 ...

随机推荐

  1. [转]ASP.NET母版页中对控件ID的处理

    一.问题提出 由于总体排版和设计的需要,我们往往创建母版页来实现整个网站的统一性,最近我由于统一性的需要,把原来整个项目单独的页面全部套用了母版页.但是出现了一个错误……在我的Blog中记录一下,方便 ...

  2. POJ 1644 分苹果 (递归解法)

    把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法. Input 第一行是测试数据的数目t(0 <= t < ...

  3. VM中Centos安装

    本例中的vm是12版本的. VM设置 首先是vm的设置,相当于是买电脑的过程 首先文件 -> 新建虚拟机 然后 然后 然后 然后 然后 然后 然后 然后 然后 然后 然后 然后 然后 点击完成之 ...

  4. 前端基础-CSS的属性相关设置

    一 字体属性 二 文本属性 三 背景属性 四 盒子模型 五 盒子模型各部分详解 一. 字体属性 1.font-weight:文字粗细(表格中*为重点) 取值 描述   normal 默认值,标准粗细 ...

  5. Python 学习笔记(九)Python元组和字典(二)

    什么是字典 字典是另一种可变容器模型,且可存储任意类型对象. 字典的每个键值 key=>value 对用冒号 : 分割,每个键值对之间用逗号 , 分割,整个字典包括在花括号 {} 中 键必须是唯 ...

  6. linux下安装使用tar

    安装tar,untar: yum install -y tar yum install -y untar 使用说明: 压缩 zip -r xxx.zip ./* 解压zip文件到当前目录 unzip ...

  7. MyBatis之Mapper XML 文件详解(四)-JDBC 类型和嵌套查询

    支持的 JDBC 类型为了未来的参考,MyBatis 通过包含的 jdbcType 枚举型,支持下面的 JDBC 类型. BITFLOATCHARTIMESTAMPOTHERUNDEFINEDTINY ...

  8. Oracle session相关数据字典(一)

    (一)session相关视图 (1)视图 v$session v$active_session_history dba_hist_active_session_history 如果是多节点数据库,v$ ...

  9. HP-UNIX平台修改Oracle processes参数报错:ORA-27154、ORA-27300、ORA-27301、ORA-27302

    OS 版本     :HP-UX B.11.31Oracle版本:11.2.0.4 (RAC) (一)问题描述 最近发现无法连接上数据库,报错信息为“ORA-00020:maximum number ...

  10. Context initialization failed org.springframework.beans.factory.BeanCreationException

    严重: Context initialization failed org.springframework.beans.factory.BeanCreationException: Error cre ...