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基础相关推荐

  1. Java基础 最近刚刚考完研准备复习一下基础 提桶进场

    Java复习 1数据类型 数值 ·整型 1 byte 8位 1字节 2 short 16位 2字节 4 int 32位 4个字节 默认 3 long 64位 8字节 ·浮点数 1 float 32 位 ...

  2. 2.1JAVA基础复习——JAVA语言的基础组成注释和常量变量

    JAVA语言的基础组成有: 1.关键字:被赋予特殊含义的单词. 2.标识符:用来标识的符号. 3.注释:用来注释说明程序的文字. 4.常量和变量:内存存储区域的表示. 5.运算符:程序中用来运算的符号 ...

  3. 调整心态,java复习要点总结。

    各位好,博主认为调整好心态是一切事情开始的良好基础.无论做任何事情,没有一个沉淀的情绪积累,都不能做到很成功.当完全融入一件事情的时候,学习效率是最高的.所以朋友,请您一定放松心态,不要有紧张的情绪. ...

  4. java开发必备基础

    Java总复习 java知识总复习 第一章:java概述: 1:Java的历史: ​ Java诞生于SUN(Stanford University Network),09年SUN被Oracle(甲骨文 ...

  5. Java复习打卡day40

    Java复习打卡day40 XML DOM 介绍 实现节点的遍历 实现节点的删除 属性的操作 创建节点 节点的复制 节点的替换 select对象 table对象 XML DOM 介绍 1.基本介绍: ...

  6. Java开发者XML基础(一)

    Java开发者XML基础(一) 2003年12月5日  作者:StoneGump  Matrix-与Java共舞     Java开发者XML基础,Part 1 原作者:Patrick Niemeye ...

  7. java to go 基础知识与区别入土指南

    java to go 基础知识与区别入土指南 文章目录 java to go 基础知识与区别入土指南 @[toc] 基础篇 关于基础类型 关于复合数据类型 关于切片 关于Map 关于sync.map ...

  8. JAVA进阶的基础知识快速通过---自学笔记(二)

    温故而知新---陆续学习陆续更新中,你有更好的记忆和学习方法,请在评论区提出来大家一起交流,认真看完,一行行代码备注看完看懂,保证学会,学不会找我. 前言: 代码学完发现很简单,很多初学者搞不明白什么 ...

  9. Java复习打卡day30

    Java复习打卡day30 前置 前置导学 HTML语言 HTML介绍 HTML语言的基础语法 常见标签 文本标签 格式化标签 图像标签 超链接标签 表格标签 表单标签 前置 前面我们主要讲述了Jav ...

最新文章

  1. android用openGl ES绘制任意方程的三维空间图形
  2. 《深入理解java虚拟机》笔记1——Java内存区域与Java对象
  3. Long Number
  4. XXX 不是当前用户的有效责任,请联系您的系统管理员
  5. Spring注解方式实现定时器
  6. 【日常填坑】之ajax请求laravel的api接口
  7. varchar和Nvarchar区别
  8. java版定时任务quartz【石英钟】
  9. centos7搭建elk
  10. 十大司机如厕友好城市出炉:苏州/杭州/成都位居前三
  11. mysql存钱用什么类型_电脑液晶显示器面板类型有哪些,显示器用什么面板比较好?...
  12. JAVA生产者消费者的实现
  13. ssm提交post_SSM中get和post乱码笔记
  14. Java基础-标识符
  15. Sqlite加密问题
  16. Jira 破解版 Docker 部署
  17. 汇编常用DOS命令调用
  18. 干货---ARCGIS拓扑规则说明详细讲解
  19. Boosting原理学习
  20. ionic2中的订单详情页面

热门文章

  1. 15分钟在阿里云Kubernetes服务上快速建立Jenkins X Platform并运用GitOps管理应用发布...
  2. RedisManager使用手册(六)-- 监控功能介绍
  3. python解释器的下载和安装
  4. 从苹果供应链谈何为云计算的业务永续
  5. Android APP开发
  6. Openssl rand命令
  7. 样条之连分式插值函数
  8. 探秘IntelliJ IDEA 13测试版新功能——调试器显示本地变量
  9. Debian读写ntfs分区格式!
  10. php 提交网页 传值 获取编辑框的值