高效并发一 Java内存模型与Java线程

本篇文章,首先了解虚拟机Java 内存模型的结构及操作,然后讲解原子性,可见性,有序性在 Java 内存模型中的体现,最后介绍先行发生原则的规则和使用.

在多数情况下让计算机同时去做几件事情,不仅是因为计算机的运算能力强大,还有一个重要的原因是计算机的运算速度与它的存储和通信子系统速度的差距太大,大量的时间都花费在磁盘 I/O, 网络通信或者数据库访问上.

1.1 硬件的效率与一致性

计算机的存储设备与处理器运算速度有很大的差距,所以加入了一层高效缓存来作为内存与处理器之间的缓冲:将运算需要的数据复制到缓冲区中,让运算快读进行,当计算完毕之后再将结果从缓冲区同步到内存.但这样做也引入一个新的问题,缓存一致性.

缓存一致性

在多处理系统中,每个处理器都有各自的高效缓存,而它们共享同一内存,当涉及到同一块主内存区域时,将可能导致缓存数据不一致.为了解决一致性的问题,需要各个处理器访问缓存时都遵循一些协议.在读写时根据协议来操作.Java 虚拟机有自己的内存模型,内存模型可以理解为在特定的操作协议下,对特定的内存或高速缓存进行读写访问的抽象过程.

为了使处理器内部单元充分利用,处理器对输入代码进行乱序执行优化,在计算之后将乱序执行的结果重组.保证结果一致.但不保证各个语句计算的先后顺序与输入代码一致.

1.2 Java 内存模型

Java 虚拟机试图定义一种 Java 内存模型来屏蔽各种硬件和操作系统的内存访问差异,实现在各个平台内存访问的一致性.

1.2.1 主内存与工作内存

Java 内存模型主要目标是定义程序中各个变量的访问规则,即虚拟机中从内存中存储和取出变量的底层细节.此处的变量与 Java 编程中的变量有所区别,包括实例字段,静态字段和构成数组对象的元素,但不包括局部变量与方法参数,因为后者是线程私有的,不会被分享.自然就不会存在竞争问题.

Java 内存模型规定所有的变量都存储在主内存中.每条线程还有自己的工作内存,工作内存中保存被该线程使用变量的主内存副本拷贝.线程中所有操作必须在工作内存进行,不能直接读写主内存中的变量,不同线程不能直接访问其它工作内存的变量,线程间的传递需要通过主内存完成.

  • lock(锁定):作用于主内存变量,将一个变量标识为一条线程独占的状态

  • unlock(解锁):作用于主内存变量,将处于锁定状态的变量释放出来,释放的变量才可以被其它线程锁定.

  • read(读取):用作于主内存变量,将一个变量的值从主内存传输到线程的工作内存,以便随后的 load 动作使用

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

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

  • assign(赋值):用作与工作内存的变量,将一个从执行引擎接收到的值赋值给工作内存的变量,当虚拟机的字节码执行遇到一个给变量赋值时执行这个操作.

  • sore(存储):作用于工作内存变量,将工作内存一个变量值传宋到主内存中,以便随后的 write 操作的使用.

  • write(写入):用作与主内存的变量,将 store 操作从工作内存中得到的值放入主内存的变量中.

如果要把一个变量从主内存复制到工作内存,就要顺序的执行 read和load 操作.如果要把变量从工作内存同步回主内存,就要顺序执行 store 和 write 操作.

1.2.3 对于 volatile 型变量的特殊规则

关键字 volatile 是 java 虚拟机提供的最轻量级的同步机制,但它并不容易完全被正确,完成地理解.

当一个变量定义为 volatile 之后,将具备两种特性,第一是保证变量对所有线程的可见性,当一个线程修改了这个变量的值,其他线程可以立即得到新值.第二是禁止指令重排序优化,普通的变量仅仅保证方法的执行过程中所有依赖赋值结果的地方都能获取到正确结果,而不能保证变量赋值操作的顺序与程序代码中的执行顺序一致.

1.2.4 原子性,可见性与有序性

原子性

基本数据类型的访问读写是具备原子性的,如果应该场景需要一个更大范围的原子性操作,在 Java 中就是使用 synchronized同步代码块操作也具备原子性.

可见性

可见性指当一个线程修改了共享变量的值,其他线程能够立即得知这个修改.

有序性

Java 内存模型中程序天然有序性可以总结为:在本线程内观察,所有操作都是有序的.如果在一个线程观察另一个线程,所有操作都是无序的.

1.2.4 先行发生原则

先行发生是Java 内存模型中定义的两项操作之间的偏序关系,如果说操作 A 先发生于操作 B ,也就是发生操作B 之前,操作 A 产生的影响能被操作 B 观察到,”影响”包括修改了内存中共享变量的值,发送了消息,调用方法等.

1.3 Java 与线程

1.3.1 线程的实现

线程是比进程更轻量级的调度单位,线程可以把一个进程的资源分配和执行调度分开,各个线程既可以共享进程资源,又可以独立调度.

实现线程主要有3种方式

  1. 使用内核线程实现

内核线程是直接由操作系统内核支持的线程,这种线程由内核来完成线程切换,内核通过操纵调度器对线程进行调度,并负责将线程的任务映射到各个处理器上.

1.2.2 内存间交互操作

但是它有局限性,首先由于是基于内核线程实现,所以各种线程操作都需要进行线程调用.而系统调用的代价相对较高,需要在用户态和内核态中来回切换.其次每个轻量级进程都需要一个内核线程支持,因此轻量级进程要消耗一定内核资源,因此一个系统支持轻量级进程的数量是有限的.具有1-5工作经验的,面对目前流行的技术不知从何下手,需要突破技术瓶颈的可以加群。在公司待久了,过得很安逸,但跳槽时面试碰壁。需要在短时间内进修、跳槽拿高薪的可以加群。如果没有工作经验,但基础非常扎实,对java工作机制,常用设计思想,常用java开发框架掌握熟练的可以加群。java架构群:591240817 一起交流。

  1. 使用用户线程实现

广义上讲,一个线程只要不是内核线程就可以认为是用户线程

狭义上的用户线程指完全建立在用户空间的线程库上.系统内核不会感知线程存在,用户线程的操作完全在用户态中完成,不需要内核的帮助.

使用用户线程的优势在于不需要系统内核支援,劣势也在于没有系统内核支援所有操作都需要用户进程自己处理.Java,Ruby 等语言曾经使用过用户进程,最终又都放弃.

  1. 使用用户线程加轻量级进程混合实现

在这种混合实现下,即存在用户线程,也存在轻量级进程.用户线程还是完全建立在用户空间中,而操作系统提供的轻量级进程则作为用户线程与讷河线程之间的桥梁,这样可以使用内核提供的线程调度功能以及处理器映射.

Java 线程的实现

在 JDK1.2中线程模型替换为基于操作系统原生线程模型来实现.因此操作系统支持怎样的线程模型,很大程度上决定了 Java 虚拟机的线程是怎样映射的.

1.3.2 Java 线程调度

线程调度是指系统为线程分配处理器使用权的过程,主要调度方式有两种:协同式线程调度和抢占式线程调度.

协同式多线程系统,线程的执行时间是由线程本身来控制.当线程工作执行完毕之后,要主动通知系统切换到另一个线程上.缺点是线程时间不可控制,容易造成程序阻塞.

抢占式调度多线程系统,每个线程由系统来分配执行时间,线程的切换不由线程本身来决定,Java 使用抢占式调度.

1.3.3 状态转换

Java 语言定义了5种线程状态,在一个线程点,一个线程只能有且只有一种状态

  • 新建,运行,等待, 阻塞, 结束

高效并发一 Java内存模型与Java线程(绝对干货)的更多相关文章

  1. 并发研究之Java内存模型(Java Memory Model)

    Java内存模型JMM java内存模型定义 上一遍文章我们讲到了CPU缓存一致性以及内存屏障问题.那么Java作为一个跨平台的语言,它的实现要面对不同的底层硬件系统,设计一个中间层模型来屏蔽底层的硬 ...

  2. 【JVM】JVM内存结构 VS Java内存模型 VS Java对象模型

    原文:JVM内存结构 VS Java内存模型 VS Java对象模型 Java作为一种面向对象的,跨平台语言,其对象.内存等一直是比较难的知识点.而且很多概念的名称看起来又那么相似,很多人会傻傻分不清 ...

  3. 【转】JVM内存结构 VS Java内存模型 VS Java对象模型

    JVM内存结构 我们都知道,Java代码是要运行在虚拟机上的,而虚拟机在执行Java程序的过程中会把所管理的内存划分为若干个不同的数据区域,这些区域都有各自的用途. 其中有些区域随着虚拟机进程的启动而 ...

  4. Java内存模型及Java关键字 volatile的作用和使用说明

    先来看看这个关键字是什么意思:volatile  [ˈvɒlətaɪl] adj. 易变的,不稳定的; 从翻译上来看,volatile表示这个关键字是极易发生改变的.volatile是java语言中, ...

  5. JAVA内存模型(Java Memory Model ,JMM)

    http://blog.csdn.net/hxpjava1/article/details/55189077 JVM有主内存(Main Memory)和工作内存(Working Memory),主内存 ...

  6. JVM内存结构 VS Java内存模型 VS Java对象模型

    前面几篇文章中, 系统的学习了下JVM内存结构.Java内存模型.Java对象模型, 但是发现自己还是对这三者的概念和区别比较模糊, 傻傻分不清楚.所以就有了这篇文章, 本文主要是对这三个技术点再做一 ...

  7. 区分 JVM 内存结构、 Java 内存模型 以及 Java 对象模型 三个概念

    本文由 简悦 SimpRead 转码, 原文地址 https://www.toutiao.com/i6732361325244056072/ 作者:Hollis 来源:公众号Hollis Java 作 ...

  8. [转帖]JVM内存结构 VS Java内存模型 VS Java对象模型

    JVM内存结构 VS Java内存模型 VS Java对象模型 https://www.hollischuang.com/archives/2509 Java作为一种面向对象的,跨平台语言,其对象.内 ...

  9. 【Java虚拟机6】Java内存模型(Java篇)

    什么是Java内存模型 <Java虚拟机规范>中曾试图定义一种"Java内存模型"(Java Memory Model,JMM)来屏蔽各种硬件和操作系统的内存访问差异, ...

随机推荐

  1. verdaccio启动命令

    1.启动项目 根目录下 verdaccio 2.npm 源管理 nrm 下载 3.nrm 源列表 nrm ls 4.nrm 源增加 nrm add verdaccio http://localhost ...

  2. 利用InsertStatusValueRequest消息为新增的statuscode设定指定值(Value)

    我是微软Dynamcis 365 & Power Platform方面的工程师罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面 ...

  3. MySQL 主从复制(实时热备)原理与配置

    MySQL是现在普遍使用的数据库,但是如果宕机了必然会造成数据丢失.为了保证MySQL数据库的可靠性,就要会一些提高可靠性的技术.MySQL主从复制可以做到实时热备数据.本文介绍MySQL主从复制原理 ...

  4. [PHP] 深度解析Nginx下的PHP框架路由实现

    所有的框架处理业务请求时,都会处理URL的路径部分,分配到指定的代码中去处理.实现这一功能的关键就是获取$_SERVER全局变量中对于URL部分的数据 当请求的路径为http://test.com/a ...

  5. Linux 设备树详解【转】

    转自:http://www.pianshen.com/article/428276673/;jsessionid=D90FC6B215155680E0B89A6D060892D4 本文基于天嵌E9V3 ...

  6. aspx使用KindEditor副文本框插件出现检测到有潜在危险

    web配置添加    <httpRuntime requestValidationMode="2.0" /> aspx页面添加   ValidateRequest=&q ...

  7. python详解json模块

    我们在做工作中经常会使用到json模块,今天就简单介绍下json模块 什么是json JSON ,全称为JavaScript Object Notation, 也就是JavaScript 对象标记,它 ...

  8. 开源敏捷测试管理& 开源BUG跟踪管理软件itest(爱测试) V3.3.1小改紧急发布及正实现功能预告

    v3.3.1 下载地址 :itest下载 码云源码地址 https://gitee.com/itestwork/itest 开源中国  itest项目地址   https://www.oschina. ...

  9. java的加载与运行

    jdk中有一个javac.exe(java编译器) *Java程序的运行包括两非常重要的阶段 -编译阶段 -运行阶段 *编译阶段 -主要任务是检查Java源程序是否符合Java语法 符合Java语法则 ...

  10. 第十六周博客作业 <西北师范大学| 周安伟>

    第十六周作业 助教博客链接https://home.cnblogs.com/u/zaw-315/ 作业要求链接https://www.cnblogs.com/nwnu-daizh/p/10980707 ...