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;
}
}
最新文章
- 微软开源 WCF 分布式服务框架,并入 .NET 基金会项目
- Redis从入门到精通之一:序篇
- 对前端的一个H5项目的所思所想
- 获取checkbox后面的文本内容
- CSS3如何去除 inline block 元素之间多出的空格
- 下载Spring的jar包的方法
- python 循环、循环设计、循环对象
- UITableView中cell的圆角(第一个和最后一个)
- SSM框架整合基本操作
- .gitconfig
- Unity暂停游戏功能
- [NOIp2018提高组]货币系统
- jquery菜单插件
- 20165321 实验三 敏捷开发与XP实践
- thinkphp 开启事物
- day 57 data 插件 表的增删改查
- Android Studio Xposed模块编写(二)
- std::string 字符串切割
- Failed to load project at 'xxx.xcodeproj', incompatible project version。
- Windows下php,mysql,apache相关安装与配置,完善中…