.java并发基础

在并发编程中存在两个关键问题①线程之间如何通信 ②线程之间如何同步。

通信

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

在共享内存的并发模型里,线程之间共享程序的公共状态,线程之间通过写-读内存中的公共状态来隐式进行通信。

在消息传递的并发模型里,线程之间没有公共状态,线程之间必须通过明确的发送消息来显式进行通信。

同步

同步是指程序用于控制不同线程之间操作发生相对顺序的机制。

在共享内存并发模型里,同步是显式进行的。程序员必须显式指定某个方法或某段代码需要在线程之间互斥访问。

在消息传递的并发模型里,由于消息的发送必须在消息的接收之前, 因此同步是隐式进行的。

Java并发采用的是共享内存模型,通信隐式进行;同步显示指定。

二.内存模型

Java内存模型JMM(Java Memory Model)主要目标是定义程序中各个变量(非线程私有)的访问规则,即在虚拟机中将变量存储到内存和从内存取出变量这样的底层细节。Java中每个线程都有自己私有的工作内存。工作内存保存了被该线程使用的变量的主内存副本拷贝,线程对变量的读写操作都必须在工作内存进行,无法直接读写主内存中的变量。两个线程无法直接访问对方的工作内存。

  • 每一个线程有一个工作内存和主存独立
  • 工作内存存放主存中变量的值的拷贝

(1)当数据从主内存复制到工作存储时,必须出现两个动作:第一,由主内存执行的读(read)操作;第二,由工作内存执行的相应的load操作;当数据从工作内存拷贝到主内存时,也出现两个操作:第一个,由工作内存执行的存储(store)操作;第二,由主内存执行的相应的写(write)操作。
(2) 每一个操作都是原子的,即执行期间不会被中断。
(3)对于普通变量,一个线程中更新的值,不能马上反应在其他变量中,如果需要在其他线程中立即可见,需要使用 volatile 关键字

内存模型的抽象:

在 Java 中,所有实例域、静态域 和数组元素存储在堆内存中,堆内存在线程之间共享。局部变量、方法定义参数 和 异常处理器参数 不会在线程之间共享,它们不会有内存可见性问题,也不受内存模型的影响。Java 线程之间的通信由 Java 内存模型(JMM)控制。JMM 决定了一个线程对共享变量的写入何时对另一个线程可见。从抽象的角度来看,JMM 定义了线程与主内存之间的抽象关系:线程之间的共享变量存储在主内存中,每一个线程都有一个自己私有的本地内存,本地内存中存储了该变量以读/写共享变量的副本。本地内存是 JMM 的一个抽象概念,并不真实存在。

JMM抽象示意图如下:

从上图来看,如果线程 A 和线程 B 要通信的话,要如下两个步骤:

1、线程 A 需要将本地内存 A 中的共享变量副本刷新到主内存去

2、线程 B 去主内存读取线程 A 之前已更新过的共享变量

步骤示意图:

举个例子:

本地内存 A 和 B 有主内存共享变量 X 的副本。假设一开始时,这三个内存中 X 的值都是 0。线程 A 正执行时,把更新后的 X 值(假设为 1)临时存放在自己的本地内存 A 中。当线程 A 和 B 需要通信时,线程 A 首先会把自己本地内存 A 中修改后的 X 值刷新到主内存去,此时主内存中的 X 值变为了 1。随后,线程 B 到主内存中读取线程 A 更新后的共享变量 X 的值,此时线程 B 的本地内存的 X 值也变成了 1。

整体来看,这两个步骤实质上是线程 A 再向线程 B 发送消息,而这个通信过程必须经过主内存。JMM 通过控制主内存与每个线程的本地内存之间的交互,来为 Java 程序员提供内存可见性保证。

内存间通信的指令:

 

Java虚拟机之内存模型的更多相关文章

  1. Java虚拟机:内存模型详解

    版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! 我们都知道,当虚拟机执行Java代码的时候,首先要把字节码文件加载到内存,那么这些类的信息都存放在内存中的哪个区域呢?当我们创建一个对象实 ...

  2. java虚拟机的内存模型

    一.为什么要了解java虚拟机的内存模型 java虚拟机作为java代码运行的平台,是java技术的基石.了解java虚拟机的内存模型也就变得十分必要.它能帮助我们更好的了解java代码的运行机制,更 ...

  3. Java虚拟机—Java8内存模型(整理版)

    1.概述 对于Java程序员来说,在虚拟机自动内存管理机制的帮助下,不再需要手动释放内存,不容易出现内存泄露和内存溢出问题.一旦出现内存泄露和溢出方面的问题,如果不了解虚拟机是怎样使用内存的,排查错误 ...

  4. 深入理解JAVA虚拟机(内存模型+GC算法+JVM调优)

    目录 1.Java虚拟机内存模型 1.1 程序计数器 1.2 Java虚拟机栈 局部变量 1.3 本地方法栈 1.4 Java堆 1.5 方法区(永久区.元空间) 附图 2.JVM内存分配参数 2.1 ...

  5. java虚拟机10.内存模型与线程

    多任务处理在现代计算机操作系统中是一项必备的功能,让计算机同时去做几件事情,不仅是因为计算机的运算能力强大了,更重要的原因是计算机的运算速度与它的存储和通信子系统速度的差距太大,大量的时间都花费在磁盘 ...

  6. 如何写出让java虚拟机发生内存溢出异常OutOfMemoryError的代码

    程序小白在写代码的过程中,经常会不经意间写出发生内存溢出异常的代码.很多时候这类异常如何产生的都傻傻弄不清楚,如果能故意写出让jvm发生内存溢出的代码,有时候看来也并非一件容易的事.最近通过学习< ...

  7. java虚拟机的内存机制

    我们都知道,java程序的跨平台性离不开java虚拟机,虚拟机隔绝了底层操作系统,使得java程序可以直接运行在虚拟机之上.所以,对java的学习,离不开对java虚拟机的学习与了解.下面简单整理下j ...

  8. 关于JAVA中的static方法、并发问题以及JAVA运行时内存模型

    一.前言 最近在工作上用到了一个静态方法,跟同事交流的时候,被一个问题给问倒了,只怪基础不扎实... 问题大致是这样的,“在多线程环境下,静态方法中的局部变量会不会被其它线程给污染掉?”: 我当时的想 ...

  9. 从Java虚拟机的内存区域、垃圾收集器及内存分配原则谈Java的内存回收机制

    一.引言: 在Java中我们只需要轻轻地new一下,就可以为实例化一个类,并分配对应的内存空间,而后似乎我们也可以不用去管它,Java自带垃圾回收器,到了对象死亡的时候垃圾回收器就会将死亡对象的内存回 ...

随机推荐

  1. 如何在SecureCRT中上传文件到linux服务器上

    1.使用yum安装运行命令sudo yum install lrzsz(默认使没有安装运行命令的) 2.上传命令rz  下载命令sz  

  2. 简单看看ReentrantLock

    前面我们分析了AQS的基本原理,然后也试着基于AQS实现了一个可重入的锁了,现在我们再来看看官方的ReentrantLock锁,这个锁是可重入的独占锁,也就是说同时只有一个线程可以获取该锁,而且这个线 ...

  3. Java对比两个数据库中的表和字段,写个冷门的东西

    Java对比两个数据库中的表和字段,写个冷门的东西 转载的 来源网络 目前所在的项目组距离下个版本上线已经很近了,就面临了一个问题:开发人员在开发库上根据需要增加数据表.数据字段.或者变更了字段类型或 ...

  4. Task使用注意

    1. CancellationTokenSource的使用 https://binary-studio.com/2015/10/23/task-cancellation-in-c-and-things ...

  5. 预备JS执行环境,预执行脚本

    page.evaluateOnNewDocument(pageFunction, ...args) pageFunction <function|string> Function to b ...

  6. jdk环境变量、maven环境变量、Mysql环境变量配置

    jdk官网地址:http://www.oracle.com/index.htmlhttp://www.java.sun.com 一.配置 jdk环境变量1.新建JAVA_HOME,在变量值复制JDK安 ...

  7. vs2010编译C++ 指向指针的指针

    #include "stdafx.h" #include <iostream> using namespace std; int _tmain(int argc, _T ...

  8. C++编程学习(十二) STL

    一.简介 标准模板库STL,是一组模板类和函数.提供了: 1.容器.用于存储信息. 2.迭代器.用于访问容器中的信息. 3.算法.操作容器内容. 1.容器 STL有两种类型的容器类: (1)顺序容器 ...

  9. 025、Java中字符串连接与加法操作一起出现

    01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...

  10. SignalTap II Logic Analyzer 无法观测到信号?

    在Quartus SignalTap 工具中加入信号,发现加入的信号变成红色,如图所示的data_slave[7..0]: 这样的信号是没有办法观测的,不会根据SignalTap 的Clock和Tri ...