Java 多线程:volatile关键字

概念


volatile 也是多线程的解决方案之一。**volatile 可以保证可见性,可是不能保证原子性。**它只能做用于变量,不能做用于方法。当一个变量被声明为 volatile 的时候,任何对该变量的读写都会绕太高速缓存,直接读取主内存的变量的值。缓存

如何理解直接读写主内存的值:回到 多线程生成的缘由(Java内存模型与i++操做解析) ,在 i++ 操做的时候,当 进行 执行引擎 对 变量 进行 + 1 以后,原来 是应该写入到 本地内存中,再由本地内存写入到主内存中,可是 因为 变量使用了 volatile 的修饰,因此 该值不会通过本地内存,而是直接写入到 主内存中去。 读取也是一样的道理。多线程

使用volatile 有两点须要注意的地方:线程

  • 运算结果并不依赖于当前值,或者能确保只有单一的线程可以修改变量的值。
  • 变量不须要和其余的状态变量共同参与不变约束

对于第一点的理解:

public class Test {
    public static volatile int i = 0;
    public static void main(String args[]){

        new Thread(new Runnable(){
            public void run(){
                for(int j = 0; j < 10000; j++)
                    i++;
                System.out.println("Thread1 end...");
            }
        }).start();

        new Thread(new Runnable(){
            public void run(){
                for(int j = 0; j < 10000; j++)
                    i++;
                System.out.println("Thread2 end...");
            }
        }).start(); 

        i++;

        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("i = " + i);
    }
}

对于第二点的理解:

private Date start;      
private Date end;      

public void setInterval(Date newStart, Date newEnd) {      
    // 检查start<end是否成立, 在给start赋值以前不变式是有效的      
    start = newStart;      

    // 可是若是另外的线程在给start赋值以后给end赋值以前时检查start<end, 该不变式是无效的      

    end = newEnd;      
    // 给end赋值以后start<end不变式从新变为有效      
}

最后,关于何时使用 volatile,通常是用来当作标记来使用。好比说,当shutdown() 方法被调用的时候,全部的 doWork() 方法都会停下来。code

相关文章
相关标签/搜索