java面试总躲不过的并发(二):volatile原理 + happens-before原则

一.happens-before原则

同一个线程中的,前面的操作 happens-before 后续的操作。(即单线程内按代码顺序执行。但是,在不影响在单线程环境执行结果的前提下,编译器和处理器可以进行重排序,这是合法的。换句话说,这一是规则无法保证编译重排和指令重排)。

1. 监视器上的解锁操作 happens-before 其后续的加锁操作。(Synchronized 规则)

2. 对volatile变量的写操作 happens-before 后续的读操作。(volatile 规则)

3. 线程的start() 方法 happens-before 该线程所有的后续操作。(线程启动规则)

4. 线程所有的操作 happens-before 其他线程在该线程上调用 join 返回成功后的操作。

5. 如果 a happens-before b,b happens-before c,则a happens-before c(传递性)

二.volatile关键字的作用

Volatile关键字主要用于保证内存可见性和顺序性:

1.volatile修饰的变量可以保证一个线程对该变量的写happens-before 一个线程对该变量的读

2.Volatile可以用来修饰long和double类型的变量使其以原子方式执行

3.Volatile在双重检查加锁的单例模式中的应用,可以防止重排序

三.volatile关键字的实现原理

在java代码编译成字节码时会在volatile修饰的共享变量进行写操作的时候会多出Lock前缀的指令。

我们知道为了提高处理速度,CPU不直接和内存进行通信,而是先将系统内存的数据读到内部缓存(L1,L2或其他)后再进行操作,但操作完不知道何时会写回内存。如果对声明了volatile的变量进行写操作,JVM就会向CPU发送一条Lock前缀的指令,将这个变量所在缓存行的数据写回到系统内存。但是,就算写回到内存,如果其他处理器缓存的值还是旧的,再执行计算操作就会有问题。所以,在多处理器下,为了保证各个CPU的缓存是一致的,就会实现缓存一致性协议,每个CPU通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了,当处理器发现自己缓存行对应的内存地址被修改,就会将当前CPU的缓存行设置成无效状态,当CPU对这个数据进行修改操作的时候,会重新从系统内存中把数据读到处理器缓存里

  1. Lock前缀的指令会引起CPU缓存写回内存;
  2. 一个CPU的缓存回写到内存会导致其他处理器的缓存失效;
  3. 当CPU发现本地缓存失效后,就会从内存中重读该变量数据,即可以获取当前最新值。

这样针对volatile变量通过这样的机制就使得每个线程都能获得该变量的最新值

volatile相关的理解就写到这里,如果大家还想详细的了解volatile可以查阅相关资料或者私信我进行交流。

并发是java中无法避免的问题,基本上java面试都会涉及一些并发相关的问题,尤其是互联网公司一定会问到,今天就先写到了这里,下次准备把并发中相关的锁和并发集合的知识整理一下分享给大家,如果喜欢记得关注我【不爱八阿哥】,有什么问题也可以私信交流,让我们共同进步。

来源:https://www.toutiao.com/i6656572928701760004/

原文地址:https://www.cnblogs.com/hahajava/p/10570959.html

时间: 2024-12-16 11:34:24

java面试总躲不过的并发(二):volatile原理 + happens-before原则的相关文章

java面试总躲不过的并发(一): 线程池ThreadPoolExecutor基础梳理

本文核心:线程池ThreadPoolExecutor基础梳理 一.实现多线程的方式 1.继承Thread类,重写其run方法 2.实现Runnable接口,实现run方法 3.实现Callable接口,实现call方法 由于Java的设计,只支持单继承,但是支持多实现形式,所以一般面向接口开发,Runnable接口与Callable接口的区别在于Callable接口中的call方法是带返回值的,其返回一个Future的异步类,我们可以通过Future的get方法获取结果,如果线程还没有执行完,g

java面试宝典之多线程和并发

和并发问题是Java技术面试中面试官比较喜欢问的问题之一.在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌握Java多线程基础知识来对应日后碰到的问题. 1. Java多线程面试问题 1.1. 进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用.而线程是在进程中执行的一个任务.Java运行环境是一个包含了不同的类和程序的单一进程.线程可以被称为轻量级进程.线程需要较少的资源来创建和驻留在进程中,并且可以共享

JAVA面试常问知识总结(二)

JAVA中的参数传递总结先看两道笔试题: 1 public class Test2 { 2 3 public static void main (String [] args) { 4 StringBuffer a = new StringBuffer ("A"); 5 StringBuffer b = new StringBuffer ("B"); 6 operate (a,b); 7 System.out.println(a+","+b);

不想搞Java了,4年经验去面试10分钟结束,现在Java面试为何这么难

作为一名优秀的程序员,技术面试都是不可避免的一个环节,一般技术面试官都会通过自己的方式去考察程序员的技术功底与基础理论知识. 如果你参加过一些大厂面试,肯定会遇到一些这样的问题: 1.看你项目都用的框架,熟悉Spring.mybatis等框架实现原理吗? 2. 看你上面有接触过消息中间件,负载均衡.RPC框架等技术吗,MySQL分库分表有做过吗? 3. 分布式架构设计,Redis分布式锁呢? 是不是看上去很难,是不是和自己准备的"题库"中的问题不一样?不知道从何处下手?如果你有这种感觉

java面试笔试题大汇总

java面试笔试题大汇总(一)JAVA相关基础知识 1.面向对象的特征有哪些方面 1.抽象:抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节.抽象包括两个方面,一是过程抽象,二是数据抽象. 2.继承:继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法.对象的一个新类可以从现有的类中派生,这个过程称为类继承.新类继承了原始类的特性,新类称为原始类的派生类(子类),

Java 面试知识点解析(二)——高并发编程篇

前言: 在遨游了一番 Java Web 的世界之后,发现了自己的一些缺失,所以就着一篇深度好文:知名互联网公司校招 Java 开发岗面试知识点解析 ,来好好的对 Java 知识点进行复习和学习一番,大部分内容参照自这一篇文章,有一些自己补充的,也算是重新学习一下 Java 吧. 前序文章链接: Java 面试知识点解析(一)--基础知识篇 (一)高并发编程基础知识 这里涉及到一些基础的概念,我重新捧起了一下<实战 Java 高并发程序设计>这一本书,感觉到心潮澎湃,这或许就是笔者叙述功底扎实的

Java面试参考指南(二)

访问修饰符 对于基本的OOPS(面向对象)概念,请看Java面试参考指南的第一部分.访问修饰符规定了一个类如何访问另一个类及它的成员(包括方法和变量). Java中有下列访问修饰符: private:私有变量和方法(非外部类)只能被声明它们的类的实例所使用. default:类中的数据.方法和它本身能够被声明为默认default.类中所有default成员都可以被本包中的其它类所访问. protected:相比default有更高的访问权限.只有成员变量和方法能够被声明为protected.父类

【Java基础】Java面试题目整理与解说(二)

1.Collection 和 Collections 的差别. Collection 是集合类的上级接口,继承于他的接口主要有 Set 和 List. Collections 是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索.排序.线程安全化等操作. 2.HashMap 和 Hashtable 的差别. HashMap 是 Hashtable 的轻量级实现(非线程安全的实现),他们都完毕了 Map 接口,HashMap是非线程安全,效率上可能高于 Hashtable.在多个线程

Java面试-数据库篇(二)

准备Java面试期间所见到的面试题和自己的整理归纳(仅供我个人学习使用的资料) 1. 主键 超键 候选键 外键 主    键: 数据库表中对储存数据对象予以唯一和完整标识的数据列或属性的组合.一个数据列只能有一个主键,且主键的取值不能缺失,即不能为空值(Null). 超    键: 在关系中能唯一标识元组的属性集称为关系模式的超键.一个属性可以为作为一个超键,多个属性组合在一起也可以作为一个超键.超键包含候选键和主键. 候选键: 是最小超键,即没有冗余元素的超键. 外    键: 在一个表中存在