您的位置:首页 > 编程语言 > Java开发

【Java多线程核心技术】---Volatile关键字

2018-03-13 23:05 246 查看

Volatile关键字

    关键字volatile的作用是使变量在多个线程可见

关键字与volatile与死循环

    关键字volatile的作用是强制从公共堆栈中取得变量的值,而不是从线程私有的数据栈中取得变量的值。

    公共堆栈的值与线程私有堆栈的值不同步造成的。
    使用volatile关键字,使线程在访问(同名)变量时,使其强制从公共堆栈中取值。volatile增加了实例变量在多个线程之间的可见性。

    公共堆栈与[b]线程私有的堆栈的区别博客:http://blog.csdn.net/onedaycbfly/article/details/53869384[/b]

    JVM为每个线程都分配了私有堆栈,这样它们之间内存是相互独立的。    线程写入volatile变量的时候,是从改变线程的本地内存,然后再刷入到公共内存。 
    线程在读取volatile变量的时候,是先从主内内存中读取最新值到本地内存,然后从本地内存中读取值,修改变量的副本synchronized 和 volatile的比较
synchronized和volatile都可以实现线程同步,但是volatile是线程同步的较为轻量级实现,volatile的性能要比synchronized好。而且volatile关键字只可以修饰变量,而synchronized可以修饰方法,以及代码块。
多线程访问synchronized会阻塞其他线程,而volatile不会发生阻塞。(除了synchronized能够保证num++的原子性操作外,重入锁ReentrantLock和原子类AtomicInteger也可以实现)
volatile不能保证num++操作的原则性,synchronized可以。
volatile解决的是多个线程之间共享变量之间的可见性,但不能保证原子性。而synchronized可以保证原子性,也可间接保证可见性,因为它将私有内存与公有内存进行了数据同步。主要解决的是多个线程访问资源的同步性问题。
线程安全:原子性,可见性
volatile的非原子特性
    volatile关键字增加了实例变量在多个线程之间的可见性,但它并不具备同步性,所以也就不具备原子性。

    关键字Volatile的使用场合是在多个线程可以感知实例变量被改变时,可从多线程读取共享变量时可以获得最新的值使用。

    关键字从volatile提示线程每次从共享内存中读取变量,而不是从私有内存中读取,这样就保证了同步数据的可见性。

    操作数据 i++,不是一个原子操作,也即非线程安全。

    1)从内存中取出 i 的值

    2)计算 i 的值

    3)将 i 的值写入到内存中。

    这是因为在进行i++计算时,另一个线程也可改变 i 的值,这就会造成出现“脏数据”,可加关键字synchronized使其同步。volatile本身并不具备处理数据的原子性,而是强制对数据的读写及时影响到主内存。

    变量在内存中工作的过程

   


    1)read和load阶段,从主复制变量到当前线程工作内存
a5ca


    2)use和assign阶段,执行代码,改变共享变量值。
    3)store和write阶段,用工作内存数据刷新主存对应变量的值。

    volatile修饰变量,JVM虚拟机只是保证从主内存加载到线程工作内存的值时最新的。volatile关键字解决的是变量读时的可见性问题,无法保证原子性,即多个线程访问同一个实例变量还是需要加锁同步。
原子类的 i ++操作
    i ++操作时使用synchronized关键字实现同步,也可使用AtomicInteger原子类进行实现。

    原子操作是不可分割的整体,没有其他线程能够中断或检查正在原子操作中的变量。一个原子操作类型就是一个原子操作可用的类型,它可以在没有锁的情况下做到线程安全。(thread-safe)

原子类并不完全安全
    实现方法是原子的,但是方法和方法之间并不是原子性。解决此问题必须使用同步。

synchronized代码块有volatile同步的功能
    关键字synchronized可以使多个线程访问同一个资源具有同步性,而且它还具有将线程工作内存的私有变量与公共内存中的变量同步的功能。关键字synchronized可以具有可视性。

    关键字synchronized可以保证在同一时刻,只有一个线程可以执行某一个方法或某一个代码块。它包含两个特性:互斥性和可见性。同步代码块不仅可以解决一个线程看到对象处于不一致的状态,还可以保证进入同步方法或者同步代码块的每个线程,都看到由一个锁保护之前的修改结果。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: