面:你怎样理解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. P1739_表达式括号匹配(JAVA语言)

    思路:刚开始想用stack,遇到'('就push,遇到')'就pop,后来发现其实我们只需要用到栈里'('的个数,所以我们用一个变量统计'('的个数就好啦~ 题目描述 假设一个表达式有英文字母(小写) ...

  2. 小白的第一次sql实战

    去年发的有一篇sql注入忘记粘贴过来了,今天想起了就fuzz过来一下 有id尝试sql注入 找这种sql注入的站用sql检索就行了,但是最好挂代理用谷歌搜索,百度的话搜sql注入的很多被别人打过了,导 ...

  3. Java 添加数字签名到Excel以及检测、删除签名

    Excel中可添加数字签名以供文档所有者申明文档的所有权或有效性.文本以Java代码示例介绍如何在Excel文档中对数字签名功能进行相关操作,包括如何添加签名到Excel.检测Excel文档是否已签名 ...

  4. 推荐模型NeuralCF:原理介绍与TensorFlow2.0实现

    1. 简介 NCF是协同过滤在神经网络上的实现--神经网络协同过滤.由新加坡国立大学与2017年提出. 我们知道,在协同过滤的基础上发展来的矩阵分解取得了巨大的成就,但是矩阵分解得到低维隐向量求内积是 ...

  5. SSM 电影后台管理项目

    SSM 电影后台管理项目 概述 通过对数据库中一张表的CRUD,将相应的操作结果渲染到页面上. 笔者通过这篇博客还原了项目(当然有一些隐藏的坑),然后将该项目上传到了Github.Gitee,在末尾会 ...

  6. 【RocketMQ源码分析】深入消息存储(3)

    前文回顾 CommitLog篇 --[RocketMQ源码分析]深入消息存储(1) ConsumeQueue篇 --[RocketMQ源码分析]深入消息存储(2) 前面两篇已经说过了消息如何存储到Co ...

  7. vuejs集成echarts的一些问题

    最近在做Beetlex的数据分析平台,在开发这个产品过程中涉及到大量的数据图表展示功能:由于产品前端使用的是vuejs开发,所以在集成echarts或多或少会碰到一些问题,在这里主要讲解一下碰到的问题 ...

  8. Linux保护机制和绕过方式

    Linux保护机制和绕过方式 CANNARY(栈保护) ​ 栈溢出保护是一种缓冲区溢出攻击缓解手段,当函数存在缓冲区溢出攻击漏洞时,攻击者可以覆盖栈上的返回地址来让shellcode能够得到执行.用C ...

  9. 浅入Kubernetes(11):了解 Service 和 Endpoint

    目录 Srevice Service 的创建及现象 Service 定义 Endpoint slices 创建 Endpoint.Service Service 创建应用 创建 Endpoint 浅入 ...

  10. Day17_106_IO_利用Buffered和BufferWriter完成复制

    利用Buffered和BufferWriter完成复制 代码示例: 用BufferedReader 和 BufferWriter完成复制 import java.io.*; public class ...