Java's Volatile Keyword

转自

http://tutorials.jenkov.com/java-concurrency/volatile.html

The Java volatile keyword is used to mark a Java variable as "being stored in main memory". More precisely that means, that every read of a volatile variable will be read from the computer‘s main memory, and not from the CPU cache, and that every write to a volatile variable will be written to main memory, and not just to the CPU cache.

Actually, since Java 5 the volatile keyword guarantees more than just that volatile variables are written to and read from main memory. I will explain that in the following sections.

Java volatile Guarantees Variable Visibility

The Java volatile keyword guarantees visibility of changes to variables across threads. This may sound a bit abstract, so let me elaborate.

In a multithreaded application where the threads operate on non-volatile variables, each thread may copy variables from main memory into a CPU cache while working on them, for performance reasons. If your computer contains more than one CPU, each thread may run on a different CPU. That means, that each thread may copy the variables into the CPU cache of different CPUs. This diagram illustrates such a situation:

With non-volatile variables there are no guarantees about when the Java Virtual Machine (JVM) reads data from main memory into CPU caches, or writes data from CPU caches to main memory. Let me explain what problems that can cause with an example:

Imagine a situation in which two or more threads have access to a shared object which contains a counter variable declared like this:

public class SharedObject {

    public int counter = 0;

}

Thread 1 could read a shared counter variable with the value 0 into its CPU cache, increment it to 1 and not write the changed value back into main memory. Thread 2 could then read the same countervariable from main memory where the value of the variable is still 0, into its own CPU cache. Thread 2 could then also increment the counter to 1, and also not write it back to main memory. Thread 1 and Thread 2 are now practically out of sync. The real value of the shared counter variable should have been 2, but each of the threads has the value 1 for the variable in their CPU caches, and in main memory the value is still 0. It is a mess! Even if the threads eventually write their value for the sharedcounter variable back to main memory, the value will be wrong.

By declaring the shared counter variable volatile the JVM guarantees that every read of the variable will always be read from main memory, and that all writes to the variable will always be written back to main memory. Here is how the volatile declaration looks:

public class SharedObject {

    public volatile int counter = 0;

}

In some cases simply declaring a variable volatile may be enough to assure that multiple threads accessing the variable see the latest written value. I will get back to which cases volatile is sufficient later.

In the situation with the two threads reading and writing the same variable, simply declaring the variable volatile is not enough. Thread 1 may read the counter value 0 into a CPU register in CPU 1. At the same time (or right after) Thread 2 may read the counter value 0 into a CPU register in CPU 2. Both threads have read the value directly from main memory. Now both variables increase the value and writes the value back to main memory. They both increment their register version of counter to 1, and both write the value 1 back to main memory. The value should have been 2 after two increments.

The problem with multiple threads that do not see the latest value of a variable because that value has not yet been written back to main memory by another thread, is called a "visibility" problem. The updates of one thread are not visible to other threads.

Since Java 5 the volatile keyword guarantees more than just the reading and writing of a variable from and to main memory.

And "visibility" problem have been solved.

Java's Volatile Keyword

时间: 2024-08-08 05:39:05

Java's Volatile Keyword的相关文章

转:java中volatile关键字的含义

转:java中volatile关键字的含义 在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言是支持多线程的,为了解决线程并发的问题,在语言内部引入了 同步块 和 volatile 关键字机制. synchronized 同步块大家都比较熟悉,通过 synchronized 关键字来实现,所有加上synchronized 和 块语句,在多线程访问的时候,同一时刻只能有一个线程能够用 sync

Java中Volatile表示什么

Java中volatile修饰符是一种用来保证不同线程之间交互的特殊机制.当一个线程修改volatile变量,另一个线程能够看到这个修改.第一个线程通知第二个线程变量已经被修改. 下面用图来解释: ready是一个volatile boolean变量, 初值设为false. answer是一个非volatile int变量,初值是0. 第一个线程准备好修改ready变量,它是两个线程交流的发送方.第二个线程读取ready变量,获取第一个线程修改的值,因此它是接收方.在两个线程交流时,在线程1修改

java中Volatile修饰符的含义

在java语言中:为了获得最佳速度,允许线程保存共享成员变量的私有拷贝,而且只当线程进入或者离开同步代码块时才与共享成员变量的原始值进行对比. volatile关键字的作用就是提示vm:对于这个成员变量不能保存它的私有拷贝,而应直接与共享变量进行交互. 被volatile修饰符修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值.而且,当成员变量发生变化时,又强迫线程将变化了的值写回共享内存,这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值.这样当多个线程同时与某个

JAVA并发--volatile

学过计算机组成原理的一定知道,为了解决内存速度跟不上CPU速度这个问题,在CPU的设计中加入了缓存机制,缓存的速度介于CPU和主存之间.在进行运算的时候,CPU将需要的数据映射一份在缓存中,然后直接操作位于缓存中的数据,操作完毕后再将缓存中的数据写回到主存.这在单线程环境中是没有任何问题的.但是在多线程环境中就大不同了. 假设现在有这样的一个场景:有两个线程thread1和thread2,他们都在操作位于主存上的一个数据int a=2(具体操作为读取a的值并执行一个自增操作).逻辑上正确的结果:

不惑JAVA之JAVA基础 - volatile

volatile在多线程并发中用途非常广,原因是它有两个特性: 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的. 禁止进行指令重排序. 内存模型的相关概念 要想弄明白volatile的原理,先需要知道内存模型的一些概念. 计算机在执行程序时,每条指令都是在CPU中执行的,而执行指令过程中,势必涉及到数据的读取和写入.由于程序运行过程中的临时数据是存放在主存(物理内存)当中的,这时就存在一个问题,由于CPU执行速度很快,而从内存读取数据和

【转】java中volatile关键字的含义

java中volatile关键字的含义 在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言是支持多线程的,为了解决线程并发的问题,在语言内部引入了 同步块 和 volatile 关键字机制. synchronized 同步块大家都比较熟悉,通过 synchronized 关键字来实现,所有加上synchronized 和 块语句,在多线程访问的时候,同一时刻只能有一个线程能够用 synchr

java中volatile关键字

java中volatile关键字 学习ImageLoader源码时遇到遇到这么一个关键字,以前没遇到过,也不明白是何含义,网上找了部分资料,总结记录一下. 在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉.Java语言是支持多线程的,为了解决线程并发的问题,在语言内部引入了 同步块 和 volatile 关键字机制. synchronized 同步块大家都比较熟悉,通过 synchronized 关键字来

2 Java基础语法(keyword,标识符,凝视,常量,进制转换,变量,数据类型,数据类型转换)

1:keyword(掌握) (1)被Java语言赋予特定含义的单词 (2)特点: 所有小写. (3)注意事项: A:goto和const作为保留字存在. B:类似于Notepad++这种高级记事本会对keyword有特殊颜色标记 2:标识符(掌握) (1)就是给类,接口.方法,变量等起名字的字符序列 (2)组成规则: A:英文大写和小写字母 B:数字 C:$和_ (3)注意事项: A:不能以数字开头 B:不能是java中的keyword C:区分大写和小写 (4)常见的命名规则(见名知意) A:

java中volatile、synchronized

先补充一下概念:Java 内存模型中的可见性.原子性和有序性. 可见性: 可见性是一种复杂的属性,因为可见性中的错误总是会违背我们的直觉.通常,我们无法确保执行读操作的线程能适时地看到其他线程写入的值,有时甚至是根本不可能的事情.为了确保多个线程之间对内存写入操作的可见性,必须使用同步机制. 可见性,是指线程之间的可见性,一个线程修改的状态对另一个线程是可见的.也就是一个线程修改的结果.另一个线程马上就能看到.比如:用volatile修饰的变量,就会具有可见性.volatile修饰的变量不允许线