首页 > 编程语言 >Think in Java 4th--Java中的volatile

Think in Java 4th--Java中的volatile

时间:2023-09-07 14:34:09浏览次数:42  
标签:Java 变量 成员 4th volatile 线程 Math


我们知道,在 Java中设置变量值的操作,除了long和double类型的变量外都是原子操作,也就是说,对于变量值的简单读写操作没有必要进行同步。

这在JVM 1.2之前,Java的

内存模型实现总是从主存读取变量,是不需要进行特别的注意的。而随着JVM的成熟和优化,现在在

多线程环境下volatile关键字的使用变得非常重要。


在当前的Java内存模型下,线程可以把变量保存在本地内存(比如机器的寄存器)中,而不是直接在主存中进行读写。这就可能造成一个线程在主存中修改了一个变量的值,而另外一个线程还继续使用它在寄存器中的变量值的拷贝,造成数据的不一致。



要解决这个问题,只需要像在本程序中的这样,把该变量声明为volatile(不稳定的)即可,这就指示JVM,这个变量是不稳定的,每次使用它都到主存中进行读取。一般说来,多任务环境下各任务间共享的标志都应该加volatile修饰。



Volatile修饰的成员变量在每次被线程访问时,都强迫从

共享内存中重读该成员变量的值。而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。



Java语言规范中指出:为了获得最佳速度,允许线程保存共享成员变量的私有拷贝,而且只当线程进入或者离开同步代码块时才与共享成员变量的原始值对比。



这样当多个线程同时与某个对象交互时,就必须要注意到要让线程及时的得到共享成员变量的变化。



而volatile关键字就是提示VM:对于这个成员变量不能保存它的私有拷贝,而应直接与共享成员变量交互。



使用建议:在两个或者更多的线程访问的成员变量上使用volatile。当要访问的变量已在synchronized代码块中,或者为常量时,不必使用。



由于使用volatile屏蔽掉了VM中必要的代码优化,所以在效率上比较低,因此一定在必要时才使用此关键字。



请看如下示例:

package ch17_concurrency;
2
3
4class UnresponsiveUI{
5 private volatile double d=1;
6 public UnresponsiveUI() throws Exception{
7 while(d>0){
8 d=d+(Math.PI+Math.E)/d;
9 }
10 System.in.read();
11 }
12}
13
14public class _19_ResponsiveUI extends Thread {
15 private static volatile double d=1;
16 public _19_ResponsiveUI(){
17 setDaemon(true);
18 start();
19 }
20 public void run(){
21 while(true){
22 //System.out.println(d); 
23 d=d+(Math.PI+Math.E)/d;
24 }
25 }
26
27 public static void main(String[] args) throws Exception {
28 // TODO Auto-generated method stub 
29 //new UnresponsiveUI(); 
30 new _19_ResponsiveUI();
31 System.in.read();
32 System.out.println(d);
33 }
34
35}
36

标签:Java,变量,成员,4th,volatile,线程,Math
From: https://blog.51cto.com/u_2544485/7396998

相关文章

  • Java中 static/transient,final/volatile 说明
    你可以任意使用如下的修改限定关键字来定义一个字段:final或者volatile和/或者static和/或者transient。如果你将一个字段定义为final,编译器将确保字段当成一个常量——只读变量来初始化和处理。因为编译器知道常量是不变的,所以在程序的字节码中对其进行了内部优化。cl......
  • 从追MM谈Java的23种设计模式
    1、FACTORY—追MM少不了请吃饭了,麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西,虽然口味有所不同,但不管你带MM去麦当劳或肯德基,只管向服务员说“来四个鸡翅”就行了。麦当劳和肯德基就是生产鸡翅的Factory.以下是引用片段:实例一:publicclassFactory{......
  • 杰哥教你面试之一百问系列:java中高级多线程concurrent的使用
    目录问题1:什么是ConcurrentHashMap?它与HashMap的区别是什么?问题2:什么是CopyOnWriteArrayList?它适用于什么样的场景?问题3:什么是BlockingQueue?它的作用是什么?举例说明一个使用场景。问题4:什么是Semaphore?它如何控制并发访问?问题5:什么是CountDownLatch?它适用于什么场景?问题6:什么是Cyc......
  • java多线程几个方法的基本概念
    一、run()和start()这两个方法应该都比较熟悉,把需要并行处理的代码放在run()方法中,start()方法启动线程将自动调用run()方法,这是由Java的内存机制规定的。并且run()方法必须是public访问权限,返回值类型为void.二、关键字Synchronized这个关键字用于保护共享数据,当然......
  • 无涯教程-JavaScript - BITAND函数
    描述BITAND函数返回两个数字的按位"AND"。语法BITAND(number1,number2)争论Argument描述Required/Optionalnumber1Mustbeindecimalformandgreaterthanorequalto0.Requirednumber2Mustbeindecimalformandgreaterthanorequalto0.Required......
  • Java的System.setProperty()和System.getProperty()
    写在前面:这里的System,系统指的是JRE(runtime)system,不是指OS。参数设置成为系统的全局变量,可以在项目的任何一个地方,通过System.getProperty("变量");来获得。System.setProperty相当于一个静态变量,存在内存里面!System.setProperty()/* *设置指定键对值的系统属性 *......
  • java内容偏多 一般有用 看1
                              ......
  • JavaNote03-流程控制语句
    0.流程控制语句流程控制语句是用来控制程序中各语句执行顺序的语句,可以把语句组合成能完成一定功能的小逻辑模块。程序设计中规定的3种流程结构,即:顺序结构程序从上到下逐行地执行,中间没有任何判断和跳转。分支结构根据条件,选择性地执行某段代码。有if…else和switch-......
  • 无涯教程-JavaScript - BIN2DEC函数
    描述BIN2DEC函数将二进制数字转换为十进制。语法BIN2DEC(number)争论Argument描述Required/Optionalnumber您要转换的二进制数。Numbercannotcontainmorethan10characters(10bits).数字的最高有效位是符号位。其余的9位是幅度位。负数使用二进制补码表示......
  • a href=#与 a href=javascript:void(0)的区别?
    一个<a>链接的按钮可在该窗口上弹出一个div悬浮层。但是每次点击,div悬浮层就自动位于IE窗口的顶端,下面的iframe窗口包含的页面会自动上移,位置错乱了。href='#'οnclick='click事件名()'></a>这里的href='#'的原因,把它改成三个#就没问题了,即修改为<ahref='###'     嘿,还真好......