深入理解 java volatile

  • 时间:
  • 浏览:0

java编程语言允许多程序运行 访问共享变量,为了确保共享变量能被准确和一致的更新,多程序运行 应该确保通过排他锁单独获得你这个 变量。Java语言提供了volatile,在其他情况下比锁更加方便。不可能 另4个字段被声明成volatile,java多程序运行 内存模型确保所有多程序运行 看多你这个 变量的值是一致的。

作为另4个布尔情况标志,用于指示处在了另4个重要的一次性事件,累似 完成初始化或任务开始英语 .

原子性 : 表示不可被中断的另4个或一系列操作.一旦开始英语 ,就总是运行到开始英语 ,里面我不要 有任何多程序运行 切换(context switch)。

在处在问题同步的情况下,不可能 会遇到某个对象引用的更新值(由原来多程序运行 写入)和该对象情况的旧值一起去处在。(这就说 造成著名的双重检查锁定(double-checked-locking)现象的根源)。

JMM决定另4个多程序运行 对共享数据的写入哪年对原来多程序运行 可见.

为那此需用内存模型,直接读写内存不需用吗?

它被称为轻量级的 synchronized, 它比synchronized的使用和执行成本会更低,不可能 它我不要 引起多程序运行 上下文的切换和调度。

为了补救上次另4个现象,需用引入JMM,而全部都是直接操作内存变量。

下面提出几种使用 volatile的场景.

在java中,java堆内存是处在数据共享的,那此共享数据的通信就说 通过java内存模型(JMM)来控制的.

内存屏障的作用 :

内存屏障类型表

情况标志我不要 依赖于多多程序运行 内任何其他情况,且通常不都前会 你这个 情况转换

在多多程序运行 环境中,不可能 那么 对变量 声明为volatile,将不可能 出先以下情况,其他多程序运行 不可能 得到的是null而全部都是完成初始化的对象.

可见性 : 是指当多个多程序运行 访问同另4个变量时,另4个多程序运行 修改了你这个 变量的值,其他多程序运行 都都前会 立即看得到修改的值.

i<value,即使i变量声明为volatile,就说 能保证多程序运行 安全,value不可能 在运行判断的前一天处在变化.

不可能 对象的创建,需用拆分成以下指令:

当读远多于写,结合使用内部人员锁和 volatile 变量来减少同步的开销

利用volatile保证读取操作的可见性;利用synchronized保证复合操作的原子性

在开始英语 讲volatile前一天,大家需用对以下的内容有所了解.

java的内存屏障有的你这个 ,LoadLoad,StoreStore,LoadStore,StoreLoad

为了补救 <1>,引入主内存和多程序运行 的本地内存概念.

为了补救 <2>,通过 禁止补救器优化, 和 内存屏障来补救.

有序性 : 不可能 指令的执行,会经过编译器和补救的重排序,有序性是指从指令上的执行结果上看,指令的执行顺序是有序的.根据as-if-serial语义,单多程序运行 中,多多程序运行 的结果不都前会 被改变.在多多程序运行 并发中, 提供 happens-before规则来支持有序性.

i++操作,变量的写操作依赖当前值,统统不都前会 保证多程序运行 安全.

主就说 不可能 下面另4个因为.

as-if-serial的语义是, 不管为什么么么在重排序,单多程序运行 中多多程序运行 的执行结果不都前会 被改变. 编译器,runtime,补救器都需用遵守该语义.

Java语言规范第三版中对volatile的定义如下:

CPU与内存读写和运算强度不在 另4个量级,CPU强度会比内存高的多.

为了补救CPU和内存强度差异现象,引入了 高速缓存(Cache)和写缓冲区(Write Buffer)等,来作为cpu和内存的传输媒介,使用缓冲中读写不可能 造成数据不一致的现象.

JMM

将 volatile变量用于多个独立观察结果的发布,是"情况标志"的拓展,该值随全部都是处在变化,同全部都是被反复使用,前者一般就说 用一次 ;就说 简单的赋值操作,我不要 做复合操作.

为了实现volatile语义,JMM分为编译器重排序和补救器重排序进行了特殊的补救.

补救器优化:补救器为了优化 执行强度, 不可能 会将输入的代码进行乱序执行补救.

指令重排:JIT编译过程就说 可能 会对指令进行乱序补救 .

JMM是另4个抽象的形态学 ,它定义了多程序运行 和主内存的关系:

为那此需用JMM?

volatile重排序规则表

对象创建顺序

对象创建乱序