600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > Java并发编程 Volatile关键字解析

Java并发编程 Volatile关键字解析

时间:2020-05-29 14:06:07

相关推荐

Java并发编程 Volatile关键字解析

volatile关键字的两层语义 一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义: 1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。 2)禁止进行指令重排序。 根据volatile的语义,我们可以看到,volatile主要针对的是并发三要素(原子性,可见性和有序性)中的后两者有实际优化作用。 可见性: 线程本身并不直接与主内存进行数据的交互,而是通过线程的工作内存来完成相应的操作。这也是导致线程间数据不可见的本质原因。因此要实现volatile变量的可见性,直接从这方面入手即可。对volatile变量的写操作与普通变量的主要区别有两点: (1)修改volatile变量时会强制将修改后的值刷新的主内存中。 (2)修改volatile变量后会导致其他线程工作内存中对应的变量值失效。因此,再读取该变量值的时候就需要重新从读取主内存中的值。 通过这两个操作,就可以解决volatile变量的可见性问题。 有序性: volatile会触发jvm的内存屏障策略 内存屏障策略: (1)LoadLoad 屏障 执行顺序:Load1—>Loadload—>Load2 确保Load2及后续Load指令加载数据之前能访问到Load1加载的数据。 (2)StoreStore 屏障 执行顺序:Store1—>StoreStore—>Store2 确保Store2以及后续Store指令执行前,Store1操作的数据对其它处理器可见。 (3)LoadStore 屏障 执行顺序: Load1—>LoadStore—>Store2 确保Store2和后续Store指令执行前,可以访问到Load1加载的数据。 (4)StoreLoad 屏障 执行顺序: Store1—> StoreLoad—>Load2 每次对volatile进行读写操作,根据上述表格,会触发对应的CPU指令,从线程内存缓冲区将之前更改的变量刷入主存。 简单来说,volatile会在一定程度上影响jvm指令集的优化策略,在volatile之前和之后的指令集不会乱序越过volatile变量执行。暂时volatile之前和之后的指令集在没有关联性的前提下,jvm可以乱序执行。 jvm的volatile策略,在一定程度上,打折扣地实现了jvm的happens-before原则(先行发生原则),如下所述。 程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作锁定规则:一个unLock操作先行发生于后面对同一个锁额lock操作volatile变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作传递规则:如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于操作C线程启动规则:Thread对象的start()方法先行发生于此线程的每个一个动作线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行对象终结规则:一个对象的初始化完成先行发生于他的finalize()方法的开始

volatile常见使用场景:

(1)状态标记量

(2)单例模式一次性安全发布

(3)低开销读写锁

参考文档: 《Java并发编程:Volatile关键字解析》/dolphin0520/p/3920373.html 《Java多线程:volatile变量,happens-before关系及内存一致性》/17149.html 《Java并发编程:volatile的使用及其原理》/paddix/p/5428507.html 《Java理论与实践:正确使用Volatile变量》/developerworks/cn/java/j-jtp06197.html

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。