线程栈(线程的工作内存)保存了线程运行时候变量值信息。当线程访问某一个对象时候值的时候,首先通过对象的引用找到对应在堆内存的变量的值,然后把堆内存变量的具体值load到线程本地内存中,建立一个变量副本,之后线程就不再和对象在堆内存变量值有任何关系,而是直接修改副本变量的值,

在修改完之后的某一个时刻(线程退出之前),自动把线程变量本的值回写到对象在堆中变量。这样在堆中的对象的值就产生变化了。下面一幅图副描述这写交互

read and load 从主存复制变量到当前工作内存 use 代码中使用值

assign  改变共享变量值  store and write 用工作内存数据刷新主存相关内容

其中use and assign 可以多次出现

但是这一些操作并不是原子性,也就是 在read load之后,如果主内存count变量发生修改之后,线程工作内存中的值由于已经加载,不会产生对应的变化,所以计算出来的结果会和预期不一样

总结:关键字上使用voildate之后,每一次use之前一定要read和load,这样就保证了可见性,其他线程

指令重排序

总结:jvm会对指令执行的顺序进行优化,这样是为了提高执行的效率。但是在单线程的情况下指令的执行先后没有关系,但是在多线程的情况下这些指令的执行顺序就是对其他线程产生很大的影响。

很多介绍JVM并发的书或文章都会谈到JVM为了优化性能,采用了指令重排序,但是对于什么是指令重排序,为什么重排序会优化性能却很少有提及,其实道理很简单,假设有这么两个共享变量a和b:

private int a;

private int b;

在线程A中有两条语句对这两个共享变量进行赋值操作:

a = 1;

b = 2;

假设当线程A对a进行复制操作的时候发现这个变量在主内存已经被其它的线程加了访问锁,那么此时线程A怎么办?等待释放锁?不,等待太浪费时间了,它会去尝试进行b的赋值操作,b这时候没被人占用,因此就会先为b赋值,再去为a赋值,那么执行的顺序就变成了:

b = 2;

a = 1;

对于在同一个线程内,这样的改变是不会对逻辑产生影响的,但是在多线程的情况下指令重排序会带来问题,看下面这个情景:

在线程A中:

context = loadContext();

inited = true;

在线程B中:

while(!inited ){

sleep

}

doSomethingwithconfig(context);

假设A中发生了重排序:

inited = true;

context = loadContext();

那么B中很可能就会拿到一个尚未初始化或尚未初始化完成的context,从而引发程序错误。

想到有一条古老的原则很适合用在这个地方,那就是先要保证程序的正确然后再去优化性能。此处由于重排序产生的错误显然要比重排序带来的性能优化要重要的多。要解决重排序问题还是通过volatile关键字,volatile关键字能确保变量在线程中的操作不会被重排序而是按照代码中规定的顺序进行访问,同时使用synchronized 关键字,里面也不会进行指令重排序。

java volidate线程安全_03.(多线程与并发)面试题-02--Volidate的原理和指令重排序相关推荐

  1. Java的多线程机制系列:(四)不得不提的volatile及指令重排序(happen-before)

    一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...

  2. 【Java 并发编程】线程指令重排序问题 ( 指令重排序规范 | volatile 关键字禁止指令重排序 )

    文章目录 总结 一.指令重排序规范 二.指令重排序示例 总结 Java 并发的 333 特性 : 原子性 : 每个操作都是 不可拆分的原子操作 ; 在线程中进行 a++ 就不是原子操作 , 该操作分为 ...

  3. JAVA:线程总结及多线程实现的两种方法

    JAVA:线程总结 目录 目录 JAVA:线程总结 JAVA:线程总结 01_多线程(多线程的引入)(了解) 02_多线程(多线程并行和并发的区别)(了解) 03_多线程(Java程序运行原理和JVM ...

  4. 【Java 并发编程】指令重排序规范 ( happens-before 先行发生原则 )

    文章目录 一.指令重排序规范 二.happens-before 先行发生原则 一.指令重排序规范 指令重排指的是 , 线程中如果两行代码 没有逻辑上的上下关系 , 可以对代码进行 重新排序 ; JVM ...

  5. Java并发编程之指令重排序

    在我们面试过程中,通常避免不了会被问到什么是指令重排序?本文就这个问题进行探索. 重排序 前言 一.重排序种类 二.happens-before 三.重排序 1.数据依赖性 2. as-if-seri ...

  6. 说说Java中原子性,可见性与指令重排序的理解

    原子性:就是读数据,处理数据,写数据 这三个步骤不能被终止,或者打断:就是不能被线程调度器中断,切换线程. 这样,才能保证,原子操作在线程切换,并行处理上保证数据地顺序累加处理. 可见性:是Jvm较为 ...

  7. java重排序_Java synchronized 能防止指令重排序吗?

    @ZealTalk 说的是 synchronized 可以防止指令重排,这个观点不对的,也欢迎回答的各位来讨论 synchronized 的有序性 来讨论这个问题先,先看看 Java 里的操作无序现象 ...

  8. 由Java引起的指令重排序思考

    背景 问题出现 最近遇到了一个NullPointerException,虽然量不大,但是很怪异,大致长这个样子 这是个什么空指针?居然说我LinkedList.iterator().hasNext() ...

  9. Java指令屏障_指令重排序和内存屏障

    sap hana计算技术项目实战指南内存 61元 (需用券) 去购买 > 一.指令重排序 指令重排序分为三种,分别为编译器优化重排序.指令级并行重排序.内存系统重排序.如图所示,后面两种为处理器 ...

最新文章

  1. 织梦生成html加速,加快DEDECMS静态html网页生成速度的方法
  2. 带你理清Node.js 的Web框架的3个层次
  3. xm console无法联接guest问题的解决
  4. Windows安装MRTG后的配置
  5. Java异常处理——try-with-resource 语法糖
  6. BZOJ 3836 Codeforces 280D k-Maximum Subsequence Sum (模拟费用流、线段树)
  7. PHP婚庆网站论文,jsp婚庆网站
  8. Bzoj2694/Bzoj4659:莫比乌斯反演
  9. 语言统计学中的几个定律,可作为设计检索的参考
  10. final个人阅读作业
  11. jeecg boot一对多新增的附表不会主键是一个string_测试开发专题:spring-boot如何使用JPA进行双向一对多配置...
  12. python爬虫慕课网利用xpath_python爬虫实践——零基础快速入门(二)爬取豆瓣电影...
  13. 了解 64 位 Office
  14. C++ String16与const char*及char*与vector相互转换
  15. Android -- TabHost
  16. 电话销售技巧,电话销售需要注意哪些?
  17. GDAL(Geospatial Data Abstraction Library )简介
  18. 【集合论】序关系 ( 哈斯图示例 | 整除关系哈斯图 | 包含关系哈斯图 | 加细关系哈斯图 )
  19. Android:InflateException: Binary XML file line #12: Error inflating class null
  20. 显卡性能暴涨,2K高清+144hz显示器飞入寻常百姓家

热门文章

  1. 谈谈两种标准库类型---string和vector
  2. CI Weekly #17 | flow.ci 支持 Java 构建以及 Docker/DevOps 实践分享
  3. vsftpd安装问题汇总(持续更新。。)
  4. Linq 学习笔记(二)
  5. java验证码的代码_java实用验证码的实现代码
  6. 用SQL语句向表格中插入数据
  7. Harbour.Space Scholarship Contest 2021-2022 (open for everyone, rated, Div. 1 + Div. 2)(A - D)
  8. 无规则弹窗自动点击插件_vscode 插件会了吧,英语不好的赶紧下载 自动分析源码中的陌生单词、点击朗读单词...
  9. RT-Thread中堆和栈内存的分配
  10. c 的word转为html5,word与html互转(1) -- word转html