• Java volatile关键字的用法


    volatile不能解决同步问题

    如果想要理解volatile关键字的作用不得不先了解Java内存模型

    摘抄一下来自百度百科的话

    在本次线程内,当读取一个变量时,为提高存取速度,编译器优化时有时会先把变量读取到一个寄存器中;以后再取变量值时,就直接从寄存器中取值;
    当变量值在本线程里改变时,会同时把变量的新值copy到该寄存器中,以便保持一致
    当变量在因别的线程等而改变了值,该寄存器的值不会相应改变,从而造成应用程序读取的值和实际的变量值不一致
    当该寄存器在因别的线程等而改变了值,原变量的值不会改变,从而造成应用程序读取的值和实际的变量值不一致
     
    Java多线程中每个线程有一个自己的工作内存,线程从主内存中copy到工作内存,进行修改等一系列操作,然后把工作内存修改后的值copy回主内存
    如果恰好此时有另一个进程同时进行这个操作,会发现意想不到的结果,和数据库中的脏读很像
     
    给变量加上了volatile后,线程将直接对主内存中的变量进行操作,也就保证了变量无论是谁来读,谁来写,都是一个值
     
    更加深入了解volatile关键字
    volatile关键字还实现了内存屏障,阻止指令重排序
     
    先来介绍一下指令重排序是什么玩意
    先来看一段代码
    public class PossibleReordering {
    static int x = 0, y = 0;
    static int a = 0, b = 0;
    
    public static void main(String[] args) throws InterruptedException {
        Thread one = new Thread(new Runnable() {
            public void run() {
                a = 1;
                x = b;
            }
        });
    
        Thread other = new Thread(new Runnable() {
            public void run() {
                b = 1;
                y = a;
            }
        });
        one.start();other.start();
        one.join();other.join();
        System.out.println(“(” + x + “,” + y + “)”);
    }

    思考一下这段代码,我们之前如果对指令重排序不了解,那么会轻易得出(x=0,y=1)或者(x=1,y=0)

    但是试一下这段代码会发现(x=0,y=0)也会出现

    说明指令并不按顺序执行,这个时候,为了确保程序如我们期望一样不会出现这个奇怪的问题,我们需要施加内存屏障

    告诉编译器,不允许你指令重排序

    ok,简单讲述了一下volatile关键字的作用,对比synchronized给对象加锁,大家可以想像成volatile是给属性加锁,修改volatile修饰的变量会比普通变量慢一点,但是读取效率是一样的,要注意的

    ,volatile关键字只是保证了变量在内存的可见性,并不保证原子性

     
     
     

     

  • 相关阅读:
    webdav srs相关
    How To Configure WebDAV Access with Apache on Ubuntu 14.04
    ubuntu 编译lighttpd
    srs编译及推流测试
    Compile pciutils (lspci, setpci) in Windows x86,在 Windows x86 平台下编译 pciutils (lspci, setpci)
    mingw MSYS2 区别
    Qt之美(三):隐式共享
    Qt之美(二):元对象
    Qt之美(一):d指针/p指针详解
    C++的栈空间和堆空间
  • 原文地址:https://www.cnblogs.com/shineyoung/p/10462052.html
Copyright © 2020-2023  润新知