说说我对java中volatile关键字的理解

首先引用两篇其他作者的文章:1.http://www.infoq.com/cn/articles/ftf-java-volatile    2.http://blog.csdn.net/hupitao/article/details/45227891

“volatile关键字能保证每个线程能读到最新的变量值”,要理解这句话首先明确cpu,寄存器,内存之间的关系。引用文中的一段话:

有volatile变量修饰的共享变量进行写操作的时候会多第二行汇编代码,通过查IA-32架构软件开发者手册可知,lock前缀的指令在多核处理器下会引发了两件事情。

  • 将当前处理器缓存行的数据会写回到系统内存。
  • 这个写回内存的操作会引起在其他CPU里缓存了该内存地址的数据无效。

处理器为了提高处理速度,不直接和内存进行通讯,而是先将系统内存的数据读到内部缓存后再进行操作,但操作完之后不知道何时会写到内存,如果对声明了Volatile变量进行写操作,JVM就会向处理器发送一条Lock前缀的指令,将这个变量所在缓存行的数据写回到系统内存。但是就算写回到内存,如果其他处理器缓存的值还是旧的,再执行计算操作就会有问题,所以在多处理器下,为了保证各个处理器的缓存是一致的,就会实现缓存一致性协议,每个处理器通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了,当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置成无效状态,当处理器要对这个数据进行修改操作的时候,会强制重新从系统内存里把数据读到处理器缓存里。

下面说一下n++操作:

被volatile修饰的n在这时会有线程安全问题,首先1.cpu会将n的值从内存读到缓存中,然后2.cpu读取缓存中的值,3.对n的值加1,然后4.写到缓存中,紧接着5.写到内存中。

线程A执行了1,2,3---让出cpu时间片---线程B也执行了1,2,3---线程A写到缓存中---线程B写到缓存中---线程A写到内存中(注意,此时强制重新从系统内存里把数据读到处理器缓存里)此时n的值被加了两次,但缓存中存的还是值加了1的值。  出现了线程安全问题。所以说volatile并不能保证原子性。

而操作:n=1+1,此之前缓存中n的值可能是旧的,那么被volatile修饰的n会强制写到内存中,寄存器会被强制刷新。

再次引用文章一段话:

1、一旦你完成写入,任何访问这个字段的线程将会得到最新的值。2、在你写入前,会保证所有之前发生的事已经发生,并且任何更新过的数据值也是可见的,因为内存屏障会把之前的写入值都刷新到缓存。

volatile为什么没有原子性?

明白了内存屏障(memory barrier)这个CPU指令,回到前面的JVM指令:从Load到store到内存屏障,一共4步,其中最后一步jvm让这个最新的变量的值在所有线程可见,也就是最后一步让所有的CPU内核都获得了最新的值,但中间的几步(从Load到Store)是不安全的,中间如果其他的CPU修改了值将会丢失。

总结:volatile关键字只能保证get操作是读取的是最新的值,而set操作会写到内存中,会强制重新从系统内存里把数据读到处理器缓存里,并不具有原子性。

时间: 2024-08-08 09:40:16

说说我对java中volatile关键字的理解的相关文章

java中volatile关键字的理解

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

转:java中volatile关键字的含义

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

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

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

java中volatile关键字

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

就是要你懂Java中volatile关键字实现原理

原文地址http://www.cnblogs.com/xrq730/p/7048693.html,转载请注明出处,谢谢 前言 我们知道volatile关键字的作用是保证变量在多线程之间的可见性,它是java.util.concurrent包的核心,没有volatile就没有这么多的并发类给我们使用. 本文详细解读一下volatile关键字如何保证变量在多线程之间的可见性,在此之前,有必要讲解一下CPU缓存的相关知识,掌握这部分知识一定会让我们更好地理解volatile的原理,从而更好.更正确地地

java中volatile关键字的含义

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

Java 中 volatile 关键字的使用注意点

锁提供了两种主要特性:互斥(mutual exclusion) 和可见性(visibility).互斥即一次只允许一个线程持有某个特定的锁,因此可使用该特性实现对共享数据的协调访问协议,这样,一次就只有一个线程能够使用该共享数据.可见性要更加复杂一些,它必须确保释放锁之前对共享数据做出的更改对于随后获得该锁的另一个线程是可见的 -- 如果没有同步机制提供的这种可见性保证,线程看到的共享变量可能是修改前的值或不一致的值,这将引发许多严重问题. 如下: import java.util.concur

java中volatile关键字的含义(转载)

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

java中volatile关键字的含义(转载自http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html)

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