Java 复习 —— JMM基础
2019独角兽企业重金招聘Python工程师标准>>>
基本内容
1、共享变量在线程间的可见性
2、synchronized实现可见性
3、volatile 实现可见性
1)指令重排序
2)as-if-serial
3)volatile 使用注意事项
4、volatile和synchronized的比较
1、可见性
一个线程对共享变量值的修改,能够及时地被其他线程看到。
共享变量:如果一个变量在多个线程的工作内存中都存在副本,那么这个变量就是这几个线程的共享变量。
Java内存模型(JMM):描述了Java程序中各种变量(共享变量)的访问规则,以及在JVM中将变量存储到内存和从内存中读取出变量这样的底层细节。
2、JMM 基本规则
1)所有的变量都存储在在主内存中。
2)每个线程都有自己独立的工作内存,里面保存该线程使用到的变量副本(主内存中该变量的一份拷贝)。
3)线程对共享变量的所有操作都必须在自己的工作内存中进行,不能直接从主内存中读写
4)不同线程之间无法直接访问其他线程工作内存中的变量,线程间变量值的传递需要通过主内存来完成。
3、共享变量实现可见性的原理
1)首先在自己线程Thread1里修改共享变量x=1
2)然后更新主内存的x=1
3)其次其他线程Thread2从主内存中读取x=1,更新自己线程的值,
这样连续性的操作,可以保证任何一个线程的独立内存中的共享变量都是最新的值!
4、Java层面实现可见性的方式
1)synchronized
2)volatile
3)concurrent 包
5、synchronized
1)线程解锁前,必须把共享变量的最新值刷新到主内存中
2)线程加锁时,将清空工作内存中共享变量的值,从而使用共享变量时需要从主内存中重新读取最新的值。(注意:加锁与解锁需要同一把锁)
6、synchronized 修饰时,JVM操作的步骤
1)首先获得互斥锁
2)清空工作内存
3)从主内存拷贝变量的最新副本到工作内存
4)执行代码
5)将更改后的共享变量值刷新到主内存
6)释放互斥锁
7、重排序
代码书写的顺序与实际执行的顺序不同,指令重排序是编译器或处理器为了提高程序性能而做的优化!
1)编译器优化
2)指令优化
3)内存系统优化
最后的结果:有可能导致代码的执行的顺序与编写顺序不一致,但是可以提高CPU性能
8、as-if-serial
无论如何重排序,程序的运行结果都是保持一致的!
单线程中是不能会因为重排序带来内存可见性的问题。
多线程则会由于重排序带来共享变量不一致的问题。
9、导致共享变量在线程间不可见的原因
1)线程交叉执行。(原子性来保证)
2)重排序结合线程交叉执行。(原子性来保证)
3)共享变量未及时更新。(内存可见性来保证)
10、synchronized 修饰变量、修饰方法或代码块
1)拥有原子性
2)拥有内存可见性
3)重量级
所以他能够实现线程间执行操作的安全性!
11、volatile 修饰变量
1)不保证原子性
2)拥有可见性
3)轻量级
12、关于 i++
1)首先读取,从主内存中读取i的值更新到当前工作内存中
2)其次改变,对i进行加1
3)最后更新,从当前工作内存中的值刷新到主内存中去
所以,这不是一个原子操作,在这个操作过程中势必会导致线程间交互而导致值的混乱!解决方式就是保证 i++ 具有原子性
1)使用synchronized
2)使用Lock对象,concurrent 包中
Lock lock = new RentrantLock();
try{
lock.lock();
i++
}finally{
lock.unlock();
}
13、volatile 使用场合
1)对变量的写入操作不依赖其当前值,比如Boolean值,但是 i++ 或 i=i+5
2)该变量没有包含在其他变量的不变式中,比如: low < high (这里我也不是很清楚)
注意:共享变量都必须是private
final 也实现了内存可见性,因为他的值是不可修改的!
14、结论
对一个共享变量不仅仅要关心他的写,还关心他的读,二者都要加锁;
volatile是轻量级的,能使用,尽量使用!
转载于:https://my.oschina.net/heweipo/blog/505891
Java 复习 —— JMM基础相关推荐
- Java基础 最近刚刚考完研准备复习一下基础 提桶进场
Java复习 1数据类型 数值 ·整型 1 byte 8位 1字节 2 short 16位 2字节 4 int 32位 4个字节 默认 3 long 64位 8字节 ·浮点数 1 float 32 位 ...
- 2.1JAVA基础复习——JAVA语言的基础组成注释和常量变量
JAVA语言的基础组成有: 1.关键字:被赋予特殊含义的单词. 2.标识符:用来标识的符号. 3.注释:用来注释说明程序的文字. 4.常量和变量:内存存储区域的表示. 5.运算符:程序中用来运算的符号 ...
- 调整心态,java复习要点总结。
各位好,博主认为调整好心态是一切事情开始的良好基础.无论做任何事情,没有一个沉淀的情绪积累,都不能做到很成功.当完全融入一件事情的时候,学习效率是最高的.所以朋友,请您一定放松心态,不要有紧张的情绪. ...
- java开发必备基础
Java总复习 java知识总复习 第一章:java概述: 1:Java的历史: Java诞生于SUN(Stanford University Network),09年SUN被Oracle(甲骨文 ...
- Java复习打卡day40
Java复习打卡day40 XML DOM 介绍 实现节点的遍历 实现节点的删除 属性的操作 创建节点 节点的复制 节点的替换 select对象 table对象 XML DOM 介绍 1.基本介绍: ...
- Java开发者XML基础(一)
Java开发者XML基础(一) 2003年12月5日 作者:StoneGump Matrix-与Java共舞 Java开发者XML基础,Part 1 原作者:Patrick Niemeye ...
- java to go 基础知识与区别入土指南
java to go 基础知识与区别入土指南 文章目录 java to go 基础知识与区别入土指南 @[toc] 基础篇 关于基础类型 关于复合数据类型 关于切片 关于Map 关于sync.map ...
- JAVA进阶的基础知识快速通过---自学笔记(二)
温故而知新---陆续学习陆续更新中,你有更好的记忆和学习方法,请在评论区提出来大家一起交流,认真看完,一行行代码备注看完看懂,保证学会,学不会找我. 前言: 代码学完发现很简单,很多初学者搞不明白什么 ...
- Java复习打卡day30
Java复习打卡day30 前置 前置导学 HTML语言 HTML介绍 HTML语言的基础语法 常见标签 文本标签 格式化标签 图像标签 超链接标签 表格标签 表单标签 前置 前面我们主要讲述了Jav ...
最新文章
- android用openGl ES绘制任意方程的三维空间图形
- 《深入理解java虚拟机》笔记1——Java内存区域与Java对象
- Long Number
- XXX 不是当前用户的有效责任,请联系您的系统管理员
- Spring注解方式实现定时器
- 【日常填坑】之ajax请求laravel的api接口
- varchar和Nvarchar区别
- java版定时任务quartz【石英钟】
- centos7搭建elk
- 十大司机如厕友好城市出炉:苏州/杭州/成都位居前三
- mysql存钱用什么类型_电脑液晶显示器面板类型有哪些,显示器用什么面板比较好?...
- JAVA生产者消费者的实现
- ssm提交post_SSM中get和post乱码笔记
- Java基础-标识符
- Sqlite加密问题
- Jira 破解版 Docker 部署
- 汇编常用DOS命令调用
- 干货---ARCGIS拓扑规则说明详细讲解
- Boosting原理学习
- ionic2中的订单详情页面