面:你怎样理解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. Java学习之随机数的用法

    •前言 随机数的产生在一些代码中很常用,也是我们必须要掌握的. 而 Java 中产生随机数的方法主要有三种: new Random() Math.random() currentTimeMillis( ...

  2. vue 快速入门 系列 —— 侦测数据的变化 - [vue 源码分析]

    其他章节请看: vue 快速入门 系列 侦测数据的变化 - [vue 源码分析] 本文将 vue 中与数据侦测相关的源码摘了出来,配合上文(侦测数据的变化 - [基本实现]) 一起来分析一下 vue ...

  3. Python常用时间转换

    1 import time 2 import math 3 4 # 定义一些时间段的常量(秒) 5 TimeSec_Hour = 3600 6 TimeSec_Day = 86400 7 TimeSe ...

  4. 截取pod ip地址最后一列

    资源清单: --- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: init-demo namespace: test ...

  5. 第23 章 : Kubernetes API 编程范式

    Kubernetes API 编程范式 需求来源 首先我们先来看一下 API 编程范式的需求来源. 在 Kubernetes 里面, API 编程范式也就是 Custom Resources Defi ...

  6. Oracle 存储结构

    数据库是存储数据的容器,它的主要功能是保存和共享数据. oracle数据库的存储结构可以分为逻辑存储结构和物理存储结构,对于这两种存储结构,oracle是分别进行管理的. 逻辑存储结构:oracle内 ...

  7. JS基础学习第一天

    JavaScript JavaScript负责页面中的的行为. 它是一门运行在浏览器端的脚本语言. JS的编写的位置 1.可以编写到标签的指定属性中 12 <button onclick=&qu ...

  8. 记一次metasploitable2内网渗透之8180端口tomcat

    扫描网段存活主机,确定内网metasploitable主机位置 nmap -T4 -sP 192.168.1.0/24 对目标主机进行扫描端口开放和系统信息 nmap -T4 -sV -Pn 192. ...

  9. Linux服务器下JMeter的安装以及Xming的使用

    1.需要安装jdk和jmeter的安装包,都可以在官网得到下载.具体的操作按照下面的指令就可以 https://www.oracle.com/cn/java/technologies/javase/j ...

  10. JavaScript课程——Day01

    1.网页由三部分组成: 1.1.HTML:超文本标记语言,专门编写网页内容的语言.(结构) 1.2.CSS:层叠样式表.(样式) 1.3.javaScript:网页交互的解释性脚本语言,专门编写客户端 ...