面:你怎样理解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. Python图像处理库——PIL

    PIL全称Python Image Library,是python官方的图像处理库,包含各种图像处理模块.Pillow是PIL的一个派生分支,包含与PIL相同的功能,并且更灵活.python3.0之后 ...

  2. 灵魂拷问!浏览器输入「xxxxhub」的背后.....

    Hey guys 各位读者姥爷们大家好,这里是程序员 cxuan 计算机网络连载系列的第 13 篇文章. 到现在为止,我们算是把应用层.运输层.网络层和数据链路层都介绍完了,那么现在是时候把这些内容都 ...

  3. js--如何实现继承?

    前言 学习过 java 的同学应该都知道,常见的继承有接口继承和实现继承,接口继承只需要继承父类的方法签名,实现继承则继承父类的实际的方法,js 中主要依靠原型链来实现继承,无法做接口继承. 学习 j ...

  4. 给Nginx配置日志格式和调整日期格式

    效果对比 官方默认日志格式 # 官方默认日志格式 log_format main '$server_name $remote_addr - $remote_user [$time_local] &qu ...

  5. [Fundamental of Power Electronics]-PART I-4.开关实现-4.2 功率半导体器件概述

    4.2 功率半导体器件概述 功率半导体设计中最根本的挑战是获得高击穿电压,同时保持低正向压降和导通电阻.一个密切相关的问题是高压低导通电阻器件的开关时间更长.击穿电压,导通电阻和开关时间之间的折衷是各 ...

  6. Python转义字符中'\'的个数问题

    Python转义字符中''的个数问题 如果字符串里面有很多字符都需要转义,就需要加很多\,为了简化,Python还允许用r' '或者r" "表示''或" "内部 ...

  7. FastDFS一步步搭建存储服务器

    一:FastDFS简介 1:FastDFS简介 FastDFS是一个开源的轻量级分布式文件系统,功能包括:文件存储.文件同步.文件访问(文件上传.文件下载)等,解决了大容量存储和负载均衡的问题.特别适 ...

  8. 【随笔】C++类静态成员变量初始化引发的惨痛教训

    事情是这样的,我在某个类中声明了一个静态的map成员, 文件名暂且称之为 xxx.h 然后在 xxx.cc 中全局定义了这个东西,静态成员在类里面只是声明,需要在外边被定义才有内存 然后又在main. ...

  9. 使用 EPPlus 封装的 excel 表格导入功能 (二) delegate 委托 --永远滴神

    使用 EPPlus 封装的 excel 表格导入功能 (二) delegate 委托 --永远滴神 前言 接上一篇 使用 EPPlus 封装的 excel 表格导入功能 (一) 前一篇的是大概能用但是 ...

  10. Go-26-Json

    JSON(JavaScript Object Notation,JavaScript对象表示法)是一种轻量级的数据交换格式,因简单.可读性强被广泛使用. Go的标准包encoding/json对JSO ...