Volatile理解

volatile作用

强制线程从公共堆栈中取得变量的值,而不是从线程私有变量中取值,解决变量在多线程之间读取的可见性。具有可见性,可是不具备原子性

synchronized作用

保证多个线程资源的同步,具有可见性和原子性,可以保证线程安

线程安全2个特点
  • 原子性:执行过程中,不会被其他线程打扰
  • 可见性:一个线程修改状态,对其他线程而言是可见的
volatile原理

每个线程访问堆中对象时,将堆中对象load到线程本地内存中,建立一个变量副本,之后线程就不再和对象在堆变量值有任何关系,而是直接修改副本变量值。
修改完之后,自动把线程变量副本的值写到对象在堆变量中。这样堆中对象的值就产生了变化。这些操作不是原子性的。
使用volatile修饰变量,JVM只是保证从内存加载到线程工作内存中的值是最新的。因此,即使使用volatile还是会存在并发情况。
比如:

  1. volatile static int a=0;
    线程A和线程B同时执行
  2. a++;

此时线程A拿到a的最新值0,线程B也拿到最新值0;但是,A执行a++后,值为1,B也同样计算得到a=1,它们再同时写回到堆内存,使得最后a的值为1,并不为2.

模拟代码如下:

public class Demo {
    public volatile static int count =0;
    @org.junit.Test
    public void Test(){
        for (int i = 0; i < 1000; i++) {//创建1000个线程执行
            new Thread(new Runnable() {
                
                @Override
                public void run() {
                    
                    doCount();
                    
                }
            }).start();
        }
        System.out.println(Demo.count);
    }
    
    
    public void doCount(){
        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        count++;
    }
}

结果会在0~1000之内摇摆不定,原因不用多说。所以,volatile不能保证数据的安全性,只能保证线程从堆中读取的是最新数据而已。

参考地址:http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html

你可能感兴趣的:(Volatile理解)