概述

  由于计算机的运算速度和它的存储和通讯子系统的速度差距巨大,大部分时间都花在IO,网络和数据库上。为了压榨CPU的运算能力,需要并发。另外,优秀的并发程序对于提高服务器的TPS有重要的意义。

硬件的效率和一致性

  由于运算速度的差距,CPU和存储设备间加入多层的cache。同时也引入了缓存一致性的问题。解决缓存一致性有多种读写协议,(MSI,MESI,MOSI,Synapse,Firefly和Dragon Protocol等。

  为了使的处理器内部的运算单元能尽量被充分利用,处理器可能会对输入的代码进行乱序执行优化,处理器会在计算之后将乱序执行的结构重组,保证结果与顺序执行的结果是一致的,但不保证程序中各个语句计算的先后顺序与输入代码中的顺序一致。,因此存在一个计算任务依赖另一个计算任务的中间结果,那么其顺序不能依靠代码的先后顺序来保证。与处理器的乱序执行优化类似,java虚拟机的即时编译器中也有类似的指令重排序优化。

Java内存模型

  Java内存模型用来屏蔽掉各种硬件和操作系统的内存访问差异,已让java程序在各种平台都能达到一致的内存访问效果。Java内存模型的目标是定义程序中各个变量的刚问规则,即在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节。

主内存与工作内存

  Java内存模型规定了变量(不含局部变量,因为局部变量线程私有,不存在共享问题)都得存放在主内存中,而每个线程对这些变量的操作都必须是从主内存中取出来并在工作内存中完成(如读取、写入的操作),不同线程之间不能访问对方的工作内存。如下图,展现了线程、主内存、工作内存之间的交互关系:


  加入一个工作内存的目的很明显,就是为了加快在内存中的操作数据的速度,因为工作内存优先存储在寄存器和高速缓存中,这两个操作的速度都远远快于主内存。主内存和工作内存之间交互的主要操作为:

  • Lock(锁定):作用于主内存的变量,将一个变量标示为一条线程独占的状态,其他线程不能访问。
  • Unlock(解锁):作用于主内存的变量,将一个处于锁定状态的变量释放出来,释放后的变量可以被其他线程锁定。
  • Read(读取):作用于主内存的变量,将一个变量的值从主内存传输到线程的工作内存,,以便进行load操作。
  • Load(加载):作用于工作内存中的变量,将read获取到的变量载入工作内存的变量副本中。
  • Use(使用):作用于工作内存中的变量,虚拟机执行引擎在执行字节码指令的时候,碰到了一个变量就会执行该操作,使用该变量。
  • Assgin(赋值):作用于工作内存中的变量,虚拟机执行引擎在执行字节码指令的时候,碰到了变量赋值的指令就会执行该操作。
  • Store(存储):作用于工作内存中的变量,将工作内存中的变量放入主内存,以便进行write操作。
  • Write(写入):作用于主内存中的变量,将store得到的变量放入主内存的变量中。

  JAva内存模型还规定了在执行上述8中操作时必须满足如下规则:

  • read 和load ,store和write 必须一对操作
  • 不允许线程丢弃assign操作,变量在工作内存中改变后必须把变化同步回主内存
  • 不允许一个线程无原因地没有发生过任何(assign操作)把数据从线程的工作内存同步回主存中
  • 新变量只能在主内存中诞生,不允许在工作内存中直接使用一个未被初始化的变量(load或assign),对一个变量实时use和store之前必须先执行过assign和load操作
  • 一个变量同一时刻值允许一条线程lock操作,但lock操作可以重复多次,执行相同数量的unlock,变量才会解锁
  • lock操作会清空工作内存副本,执行引擎使用前,需要执行load或者assign操作初始化变量的值
  • 没有lock操作,就不允许unlock操作。不允许unlock另一个线程变量。
  • unlock操作前必须先把此变量同步回主内存中(执行store,write操作)

  虚拟机允许将没有被volatile修饰的64位数据的读写操作划分为两次32位的操作来进行。

Happens-Before原则

  • 程序顺序规则:在一个线程内,按照程序代码顺序,书写在前面的操作先行发生于书写在后面的操作。
  • 管理锁定规则:一个unlock操作先于后面对同一个锁的lock操作。
  • Volatile变量规则:对一个volatile变量的写操作必须在对该变量的读操作之前发生。
  • 线程启动规则:线程的Thread.start()方法必须在该线程所有其他操作之前发生。
  • 线程终止规则:线程中所有操作都先行发生于该线程的终止检测。可以通过Thread.join()方法结束、Thread.isAlive()的返回值判断线程是否终止。
  • 线程中断规则:对线程interrupt()方法的调用必须在被中断线程的代码检测到interrupt调用之前执行。
  • 对象终结规则:对象的初始化(构造函数的调用)必须在该对象的finalize()方法完成。
  • 传递性:如果A先行发生于B,B先行发生于C,那么A先行发生于C。

关键概念

  并发,在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行。

  并行:在操作系统中是指,一组程序按独立异步的速度执行,不等于时间上的重叠(同一个时刻发生)。

  多线程(英语:multithreading),是指从软件或者硬件上实现多个线程并发执行的技术。

  同步就是协同步调,按预定的先后次序进行运行。

  线程安全:当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在主调代码中不需要任何额外的同步或者协同,这几个类都能表现出正确的行为,那么就成这个类是线程安全的。

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

  1. java内存模型与线程(转) good

    java内存模型与线程 参考 http://baike.baidu.com/view/8657411.htm http://developer.51cto.com/art/201309/410971_ ...

  2. Java并发程序设计(三) Java内存模型和线程安全

    Java内存模型和线程安全 一 .原子性 原子性是指一个操作是不可中断的.即使是在多个线程一起执行的时候,一个操作一旦开始,就不会被其它线程干扰. 思考:i++是原子操作吗?  二.有序性 Java代 ...

  3. 深入理解java虚拟机-第12章Java内存模型与线程

    第12章 Java内存模型与线程 Java内存模型  主内存与工作内存: java内存模型规定了所有的变量都在主内存中,每条线程还有自己的工作内存. 工作内存中保存了该线程使用的主内存副本拷贝,线程对 ...

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

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

  5. (Java多线程系列七)Java内存模型和线程的三大特性

    Java内存模型和线程的三大特性 多线程有三大特性:原子性.可见性.有序性 1.Java内存模型 Java内存模型(Java Memory Model ,JMM),决定一个线程对共享变量的写入时,能对 ...

  6. 深入理解Java虚拟机(第三版)-13.Java内存模型与线程

    13.Java内存模型与线程 1.Java内存模型 Java 内存模型的主要目的是定义程序中各种变量的访问规则,即关注在虚拟机中把变量值存储到主内存和从内存中取出变量值的底层细节 该变量指的是 实例字 ...

  7. 一夜搞懂 | Java 内存模型与线程

    前言 本文已经收录到我的 Github 个人博客,欢迎大佬们光临寒舍: 我的 GIthub 博客 学习导图 一.为什么要学习内存模型与线程? 并发处理的广泛应用是 Amdah1 定律代替摩尔定律成为计 ...

  8. Java内存模型与线程(一)

    Java内存模型与线程 TPS:衡量一个服务性能的标准,每秒事务处理的总数,表示一秒内服务端平均能够响应的总数,TPS又和并发能力密切相关. 在聊JMM(Java内存模型)之前,先说一下Java为什么 ...

  9. 《深入了解java虚拟机》高效并发读书笔记——Java内存模型,线程,线程安全 与锁优化

    <深入了解java虚拟机>高效并发读书笔记--Java内存模型,线程,线程安全 与锁优化 本文主要参考<深入了解java虚拟机>高效并发章节 关于锁升级,偏向锁,轻量级锁参考& ...

  10. java内存模型和线程

    概述 多任务的处理在现在的计算机中可以说是"标配"了,在许多的情况下,让计算机同时做几件事情,不仅是因为计算机的运算能力的强大,还有一个重要的原因是:cpu的运算速度和计算机的存储 ...

随机推荐

  1. ArcEngine保存栅格数据至rastercatalog

    将栅格数据(IRasterDataset)直接保存到数据库中很常见,但是保存到栅格目录下就比较少见,好不容易才找到,在这里记录一下. public void saveRasterDs2Catalog( ...

  2. QT Creator 快速入门教程 读书笔记(三)

    一   信号和槽 GUI 程序除了要绘制控件,还要响应系统和用户事件,例如重绘.绘制完成.点击鼠标.敲击键盘等.当事件发生时,UI 会产生相应的变化,让用户直观地看到. 大部分编程(例如Win SDK ...

  3. java iframe 嵌套,session失效重新登录页面嵌套问题

    将后台跳转改写成 PrintWriter out = response.getWriter(); out.println("<html>");    out.print ...

  4. SQL 游标的应用

    ----------------SQL游标应用-----------------if object_id('tempdb..#test0001') is not null drop table #te ...

  5. Html5 Canvas笔记(2)-Canvas绘图

    用Canvas API绘图,需要画图形的边线并设置内部区域填充,边线英文语法对应stroke,填充对应fill,在后面我们会频繁看到这2个英文单词的出现.Canvas API内置的形状绘图函数比较少, ...

  6. window.onload与document.ready的区别

    1. window.onload必须等到网页中所有的内容加载完(包含图片)才执行 document.ready网页中所有DOM结构绘制完执行,可能DOM并没有加载完 所有document.ready比 ...

  7. C#重的数组、集合(ArrayList)、泛型集合(list<T>)三者比较及扩展延伸……

    本来我只想总结下数组.集合(ArrayList).泛型集合(list<T>)三者的比较的,可以一写下来要扩展的知识点有点多了,只能写一个小的知识点列表了如下: 1.数组.集合(ArrayL ...

  8. mock.js-无需等待,随机产生数据,让前端独立于后端进行开发

    mock.js所做的 基于 数据模板 生成模拟数据. 基于 HTML模板 生成模拟数据. 拦截并模拟 ajax 请求. Mock.js官方网址:http://mockjs.com/ 1.Mock.js ...

  9. C#委托冒泡

    委托的实现,就是编译器自行定义了一个类:有三个重要参数1.制定操作对象,2.指定委托方法3.委托链 看如下一个列子: class DelegatePratice { public static voi ...

  10. Python爬虫 Cookie的使用

    Cookie,指某些网站为了辨别用户身份.进行session跟踪而储存在用户本地终端上的数据(通常经过加密) 比如说有些网站需要登录后才能访问某个页面,在登录之前,你想抓取某个页面内容是不允许的.那么 ...