volatile 关键字都知道是不能做到线程同步的,只能保证线程之间尽快的获取最新的值,像 concurrentHashmap 之间 value 的修饰就用到了 volatile,我感觉这个关键在没啥用的感觉,,,求解释。
或者说 volatile变量修饰符适用于什么场景?
在并发编程中,我们通常会遇到以下三个问题:原子性问题,可见性问题,有序性问题。
volatile关键字的作用是解决可见性问题的,但不能保证原子性,如果要保证原子性,还需要使用锁(synchronized,Lock,CAS)。
synchronized关键字是防止多个线程同时执行一段代码,那么就会很影响程序执行效率,而volatile关键字在某些情况下性能要优于synchronized,下面列举几个Java中使用volatile的几个场景。
1.状态标记量
volatile boolean flag = false;
while(!flag){
doSomething();
}
public void setFlag() {
flag = true;
}
volatile boolean inited = false;
//线程1:
context = loadContext();
inited = true;
//线程2:
while(!inited ){
sleep()
}
doSomethingwithconfig(context);
2.double check
class Singleton{
private volatile static Singleton instance = null;
private Singleton() {
}
public static Singleton getInstance() {
if(instance==null) {
synchronized (Singleton.class) {
if(instance==null)
instance = new Singleton();
}
}
return instance;
}
}
关于java volatile, 有几点说明
volatile保证 可见性. 即线程得到的 值是 最新的. Thread1 改变了 var的值, 那么Thread2再去读, 就是改变了的值, 而不是以前的. 再具体一点, 我的理解是这样(有误请指出), 现代计算机都是多核或多cpu, 一个变量可能在同一时间, 存在与不同的cpu的 寄存器里. 如果没有volatile做保证, 那么同一时间 统一变量会有不同的值. volatile保证每次都是从 主存中读取/写入 变量的值, 从而保证可见性.
volatile保证 编译器不会过度优化. 见过以下的例子, 大概的代码是这样:
public class Thread1 extends Thread {
private boolean flag = false;
public void run() {
while(!flag) {
// ...
}
}
public void close() {
flag = true;
}
}
但是在外部进程调用close()后, Thread1并没有退出. 用了jdk debug版本 拿到了hotspot 的汇编码. 发现这里while(!flag) 被编译器优化为 while(true).
对long或double来说, 读写不是 原子操作. 加了volatile, 对long或double的读写为 原子操作.
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。