Java中volatile关键字你真的理解了吗?
面:你怎样理解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关键字你真的理解了吗?的更多相关文章
- 【转】java中volatile关键字的含义
java中volatile关键字的含义 在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言 ...
- 转:java中volatile关键字的含义
转:java中volatile关键字的含义 在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言 ...
- Java中Volatile关键字详解 (转自郑州的文武)
java中volatile关键字的含义:http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html 一.基本概念 先补充一下概念:J ...
- java中volatile关键字的理解
一.基本概念 Java 内存模型中的可见性.原子性和有序性.可见性: 可见性是一种复杂的属性,因为可见性中的错误总是会违背我们的直觉.通常,我们无法确保执行读操作的线程能适时地看到其他线程写入的值,有 ...
- Java中Volatile关键字详解
一.基本概念 先补充一下概念:Java并发中的可见性与原子性 可见性: 可见性是一种复杂的属性,因为可见性中的错误总是会违背我们的直觉.通常,我们无法确保执行读操作的线程能适时地看到其他线程写入的值, ...
- Java中Volatile关键字详解(转载)
转载自:https://www.cnblogs.com/zhengbin/p/5654805.html 一.基本概念 先补充一下概念:Java 内存模型中的可见性.原子性和有序性. 可见性: 可见性是 ...
- 就是要你懂Java中volatile关键字实现原理
原文地址http://www.cnblogs.com/xrq730/p/7048693.html,转载请注明出处,谢谢 前言 我们知道volatile关键字的作用是保证变量在多线程之间的可见性,它是j ...
- 白话讲述Java中volatile关键字
一.由一段代码引出的问题 首先我们先来看这样一段代码: public class VolatileThread implements Runnable{ private boolean flag = ...
- Java中volatile关键字解析
一.内存模型的相关概念 大家都知道,计算机在执行程序时,每条指令都是在CPU中执行的,而执行指令过程中,势必涉及到数据的读取和写入.由于程序运行过程中的临时数据是存放在主存(物理内存)当中的,这时就存 ...
随机推荐
- Cookie与Session的安全性
说到cookie与session我们首先要说一下为什么要引入这两个东西,这两个多西到底是干什么的 起源 由于HTTP协议使无状态的: 每一次请求都是新的请求,不会记得之前通信的状态 客户端与服务端的一 ...
- Istio安全-证书管理(实操一)
Istio安全-证书管理 目录 Istio安全-证书管理 插入现有CA证书 插入现有证书和密钥 部署Istio 配置示例services 校验证书 卸载 Istio的DNS证书管理 DNS证书的提供和 ...
- 批处理文件设置IP以及DNS
先附上批处理文件代码(批处理文件怎么创建自己另行百度,这里不再赘述) Echo offecho ==============请输入序号修改办公区===========echo *********1.家 ...
- 北航OO第一单元作业总结(1.1~1.3)
经过了三次作业之后,OO第一单元告一段落,作为一个蒟蒻,我初步了解了面向对象的编程思想,并将所学内容用于实践. 一.第一次作业 1.架构分析 本次作业需要完成的任务为简单多项式导函数的求解.表达式仅支 ...
- OO第二单元作业——魔鬼电梯
简介 本单元作业分为三次 第一次作业:第一次作业要实现单部简单电梯,停靠所有楼层,无载客容量,性能分考量电梯运行时间. 第二次作业: 第二次作业实现多部电梯,电梯数量由初始化设定,每部电梯都停靠所有楼 ...
- 2020-BUAA OO-面向对象设计与构造-HW11中对ageVar采用缓存优化的等价性证明(包括溢出情况)
HW11中对ageVar采用缓存优化的等价性证明(包括溢出情况) 概要 我们知道,第三次作业里age上限变为2000,而如果缓存年龄的平方和,2000*2000*800 > 2147483647 ...
- libnet的使用详解
最近搬砖需要对libnet进行介绍在这里对知识进行汇总. 1.libnet简介 在libnet出现以前,如果要构造数据包并发送到网络中,程序员要通过一些复杂的接口来处理.libnet的出现,为程序员提 ...
- gdb常用命令(转)
pwn常常会用到gdb,看到一篇不错的文章,记录了很多命令:https://www.jianshu.com/p/c3e5f5972b21 gdb 基础调试命令 s step,si步入 n 执行下一条指 ...
- xctf - forgot
xctf - forgot check一下,开启了NX 拉入ida中,能找到: __isoc99_scanf,能够无限输入, 循环中,读取32个scanf的字符并进行判断,最后根据结果调用存在栈上的函 ...
- Vue CLI 是如何实现的 -- 终端命令行工具篇
Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统,提供了终端命令行工具.零配置脚手架.插件体系.图形化管理界面等.本文暂且只分析项目初始化部分,也就是终端命令行工具的实现. 0. 用法 ...