面:你怎样理解volatile关键字时?

我:不加思索的说出,volatile修饰的成员变量,可保证线程可见性、不保证原子性和禁止指令重排。

面:你能谈谈什么是线程可见性吗?

我:各个线程对主内存中共享变量的操作都是各个线程各自拷贝到自己的工作内存进行操作,操作完成后再写回主内存中的.例如一个线程AAA修改了共享变量X的值还未写回主内存中时 ,另外一个线程BBB又对

内存中的一个共享变量X进行操作,但此时A线程工作内存中共享变量X对线程B来说并不不可见。这种工作内存与主内存同步延迟现象就造成了可见性问题。

面:你能通过代码验证线程可见性吗?

我:  好的,写出以下代码,以为很完美,运行也正常,心里美滋滋

class Child{

    private volatile  boolean cry = false;

    public boolean isCry() {
return cry;
} public void setCry(boolean cry) {
this.cry = cry;
} }
public class MainTest { public static void main(String[] args) {
Child child = new Child(); new Thread(()->{
try {
System.out.println("开始循环");
while (!child.isCry()) {
System.out.println("观察宝宝。。。。。");
};
System.out.println("结束循环");
} catch (Exception e) {
e.printStackTrace();
}
}).start(); new Thread(()->{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
child.setCry(true);
System.out.println("宝宝醒了。。。。");
}).start(); System.out.println("==============="); }
}

面:你把volatile关键字删除,然后在运行一下?

我:运行一下发现,也能正常结束,我靠为什么会这样呢?我心里开始慌了,然后支支吾吾的。。。。

面:你看过System.out.println();的源码吗?

我:我又慌了,我说没看过(其实真没看过),肯定感觉我平时不怎么思考,而且刚才还再问volatile关键字怎么跳到这了呢。。。。

面:因为println()方法里面加了synchronized,而你在循环里里面调用了该方法,所以你懂了吧

 public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}  

我:我说大致明白了,因为synchronized能保证线程安全,肯定也具有线程可见性。

面:你这样理解也行,但是在使用了synchronized上锁这个操作后线程会做以下操作:

  1.获得同步锁

  2.清空工作内存

  3.从主内存中拷贝对象副本到本地内存

  4.执行代码(打印语句或加加操作)

  5.刷新主内存数据

  6.释放同步锁

面:volatile不能保证原子性,那你再不加锁的情况怎样保证原子性

我:我会结合java.util.concurrent.atomic包下的类配合使用,因为该包下的类可以保证原子性,通过CAS(比较并交换,个人理解:轻量级自旋锁)方式

面:你了解指令重排的含义吗?

我:大概了解一点,比如n++;它其实会被编译成四条指令,

//伪代码
public void test(){
n++;
}
//反编译字节码
public void test();
Code:
0: aload_0
1: dup
2: getfield #2 // Field n:I
5: iconst_1
6: iadd
7: putfield #2 // Field n:I
10: return
}

面:恩,那你有时间可以内存屏障的概念,这样才能更深入的理解。

我:好的

面:那你在工作中如何使用volatile?

我:DCL单例模式,其它场景主要使用volatile的线程可见性

public class DCLSingleton {

    private static volatile DCLSingleton instance;

    private DCLSingleton(){

    }

    public static DCLSingleton getInstance(){
if(null == instance){
synchronized (DCLSingleton.class){
if(null == instance){
instance = new DCLSingleton();
}
}
}
return instance;
}
}  

Java中volatile关键字你真的理解了吗?的更多相关文章

  1. 【转】java中volatile关键字的含义

    java中volatile关键字的含义   在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言 ...

  2. 转:java中volatile关键字的含义

    转:java中volatile关键字的含义 在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言 ...

  3. Java中Volatile关键字详解 (转自郑州的文武)

    java中volatile关键字的含义:http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html 一.基本概念 先补充一下概念:J ...

  4. java中volatile关键字的理解

    一.基本概念 Java 内存模型中的可见性.原子性和有序性.可见性: 可见性是一种复杂的属性,因为可见性中的错误总是会违背我们的直觉.通常,我们无法确保执行读操作的线程能适时地看到其他线程写入的值,有 ...

  5. Java中Volatile关键字详解

    一.基本概念 先补充一下概念:Java并发中的可见性与原子性 可见性: 可见性是一种复杂的属性,因为可见性中的错误总是会违背我们的直觉.通常,我们无法确保执行读操作的线程能适时地看到其他线程写入的值, ...

  6. Java中Volatile关键字详解(转载)

    转载自:https://www.cnblogs.com/zhengbin/p/5654805.html 一.基本概念 先补充一下概念:Java 内存模型中的可见性.原子性和有序性. 可见性: 可见性是 ...

  7. 就是要你懂Java中volatile关键字实现原理

    原文地址http://www.cnblogs.com/xrq730/p/7048693.html,转载请注明出处,谢谢 前言 我们知道volatile关键字的作用是保证变量在多线程之间的可见性,它是j ...

  8. 白话讲述Java中volatile关键字

    一.由一段代码引出的问题 首先我们先来看这样一段代码: public class VolatileThread implements Runnable{ private boolean flag = ...

  9. Java中volatile关键字解析

    一.内存模型的相关概念 大家都知道,计算机在执行程序时,每条指令都是在CPU中执行的,而执行指令过程中,势必涉及到数据的读取和写入.由于程序运行过程中的临时数据是存放在主存(物理内存)当中的,这时就存 ...

随机推荐

  1. 模拟实现AMD模块化规范

    目录 引子 再谈什么是闭包(闭包的产生)? 词法作用域 回到闭包 利用闭包编写模块 实现AMD模块化规范 写在最后 引子 本文最后的目的是模拟实现AMD模块化规范,而写下本文的原因是今天阅读到了< ...

  2. Win10环境下YOLO5 快速配置与测试

    目录 一.更换官方源 二.安装Pytorch+CUDA(python版本) 三.YOLO V5 配置与验证 四.数据集测试 五.小结 不想看前面,可以直接跳到标题: 一.更换官方源 在 YOLO V5 ...

  3. Myabtis-Plus之QueryWrapper常用方法

    AbstractWrapper 下的方法及使用 方法名 说明 使用 allEq(Map<R, V> params) 全部 =(或个别 isNull) allEq(params,true) ...

  4. WordPress的SEO优化技巧

    世界上大约有30%的网站都是由Wordpress搭建的,因为Wordpress自身构架清晰,代码规范,且网页评论直接书写在整个页面里,能够被搜索引擎检索到,因此对搜索引擎很友好.但有时候还是会出现只被 ...

  5. 集合Set添加多个元素

    方一 Integer[] x=new Integer[]{4,6,9,10}; Set<Integer> set = new HashSet<>() ; Collections ...

  6. Horovod in Docker

    https://horovod.readthedocs.io/en/stable/docker.html Step1 构建镜像 GPU $ mkdir horovod-docker-gpu $ wge ...

  7. Css预编语言以及区别

    一.是什么 Css 作为一门标记性语言,语法相对简单,对使用者的要求较低,但同时也带来一些问题 需要书写大量看似没有逻辑的代码,不方便维护及扩展,不利于复用,尤其对于非前端开发工程师来讲,往往会因为缺 ...

  8. 2.7w字!Java基础面试题/知识点总结!(2021 最新版)

    这篇<Java 基础知识总结>是 JavaGuide 上阅读量最高的一篇文章,由于我对其进行了重构完善并且修复了很多小问题,所以,在博客园再同步一下! 文章内容比较多,目录如下: 基础概念 ...

  9. Python 面像对象编程(上)

    一: 对象的概念 "面向对象"的核心是"对象"二字,而对象的精髓在于"整合",什么意思? 所有的程序都是由"数据"与&q ...

  10. k8s 使用nfs做provisioner

    官方的nfs provisoner,serviceAccount RABC相关 请在这里下载https://raw.githubusercontent.com/kubernetes-incubator ...