• volatile


    volatile是什么

    对于volatile, <The Java Language Specification Third Edition>是这样描述的

    “A field may be declared volatile, in which case the Java memory model ensures that all threads see a consistent value for the variable.”
    意思是,如果一个变量声明为volatile, Java 内存模型保证所有的线程看到这个变量的值是一致的。
     
    “… the volatile modifier guarantees that any thread that reads a field will see the most recently written value.” - Josh Bloch
    Josh Bloch 说 ”volatile描述符保证任意一个程序读取的是最新写的值“
     
    有人会问,内存不是存放变量值的地方吗,线程T1写,然后线程T2读,怎么会出现不一致的情况呢。

    缓存

    实际上内存不是唯一存储变量的地方。CPU往往会把变量的值存放到缓存中。假如一个CPU,即使在多线程环境下也不会出现值不一致的情况。但是,在多CPU,或者多核CPU的情况就不是这样了。如下图所示,在多个CPU情况下,每个CPU都有独立的缓存,CPU通过连接相互获取缓存内容。线程T1的可能运行在CPU 0上,它从内存中读取值放到缓存中做运算,比如执行方法foo;线程T2运行于CPU 1上,执行方法bar。
     void foo(void)
     {
       a = 1;
       b = 1;
      }
    
     void bar(void)
     {
      while (b == 0) continue;
      assert(a == 1);
     }

     在多CPU情况下,由于CPU各自缓存的原因,线程可能观察到不一致的变量值。

    按我的理解,volitate标志通过CPU基本的指令,比如(mfence x86 Xeon 或 membar SPARC)添加内存界限,让缓存和内存之间的值进行同步。 

    参考资料:

    Memory Barrierhttp://en.wikipedia.org/wiki/Memory_barrier 

    为什么需要Memory Barrier http://www.rdrop.com/users/paulmck/scalability/paper/whymb.2010.06.07c.pdf

    Java 内存模型和Memory Barrier www.infoq.com/articles/memory_barriers_jvm_concurrency

    volatile的一个作用

    由于volatile保证一些线程写的值,另外一些线程能够立即看得到。我们可以通过这一特性,实现信号或事件机制。比如下面程序里主线程可以发送信号(把stopSignal设为true), 把线程workerThread立即终止。

    public class  WorkerOwnerThread
    
    {
    
        // field is accessed by multiple threads.
    
        private static  volatile boolean  stopSignal;
    
    
    
        private static  void  doWork()
    
        {
    
            while (!stopSignal)
    
            {
    
            Thread t = Thread.currentThread();  
    
            System.out.println(t.getName()+ ": I will work until i get STOP signal from my Owner...");
    
            }
    
        System.out.println("I got Stop signal . I stop my work");
    
        }
    
    
    
        private static   void stopWork()
    
        {
    
        stopSignal = true;
    
        //Thread t = Thread.currentThread();  
    
        //System.out.println("Stop signal from " + t.getName()  ); 
    
        }
    
      
    
      
    
        public static void main(String[] args) throws InterruptedException {
    
    
    
        Thread workerThread = new Thread(new Runnable() {
    
            public void run() {
    
                doWork();    } 
    
            });
    
        workerThread.setName("Worker");
    
        workerThread.start();
    
    
    
        //Main thread
    
        Thread.sleep(100);
    
        stopWork();
    
        System.out.println("Stop from main...");
    
        }
    
    }
  • 相关阅读:
    GPIO推挽输出和开漏输出详解
    Linux驱动中completion接口浅析(wait_for_complete例子,很好)【转】
    当JAVA集合移除自身集合元素时发生的诸多问题
    Machine Learning #Lab1# Linear Regression
    Nth to Last Node in List
    Codeforces Round #272 (Div. 2)AK报告
    iOS 使用Block实现函数回调
    ios上禁止输入表情
    POJ 1287:Networking(最小生成树Kruskal)
    CSS实现强制换行-------Day 78
  • 原文地址:https://www.cnblogs.com/cando/p/2695751.html
Copyright © 2020-2023  润新知