开发者社区> 问答> 正文

关键字volatile的作用

volatile 关键字都知道是不能做到线程同步的,只能保证线程之间尽快的获取最新的值,像 concurrentHashmap 之间 value 的修饰就用到了 volatile,我感觉这个关键在没啥用的感觉,,,求解释。
或者说 volatile变量修饰符适用于什么场景?

展开
收起
蛮大人123 2016-03-04 16:32:03 3277 0
3 条回答
写回答
取消 提交回答
  • volatile 关键字作用是,使系统中所有线程对该关键字修饰的变量共享可见,可以禁止线程的工作内存对volatile修饰的变量进行缓存。
    2019-07-17 18:52:30
    赞同 展开评论 打赏
  • 在并发编程中,我们通常会遇到以下三个问题:原子性问题,可见性问题,有序性问题。

    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;
        }
    }
    2019-07-17 18:52:30
    赞同 展开评论 打赏
  • 我说我不帅他们就打我,还说我虚伪

    关于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的读写为 原子操作.

    2019-07-17 18:52:30
    赞同 展开评论 打赏
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载