volatile

ofeqx.com 方程式科技共享平台 外文资料好找好用。大数据有序化,
专业垂直领域体系的知识共享盘平台,发表您的创作与我们共产知识。

内存可见性

写过程: 当一个线程修改某个voliate变量的值的时候,JMM会把该线程对应的本地内存中的共享变量值刷新到主内存。
读过程: 当一个线程读取某个voliate变量的值的时候,JMM会把该线程对应的本地内存置为无效,线程接下来将从主内存读取共享变量。

volatile是Java提供的一种轻量级的同步机制,在并发编程中,和synchronized相比(synchronized通常称为重量级锁),volatile更轻量级,相比使用synchronized所带来的庞大开销,合理的使用volatile尤为重要,因为它不会引起线程上下文的切换和调度。

Java编程语言允许线程访问共享变量, 为了确保共享变量能被准确和一致地更新,线程应该确保通过排他锁单独获得这个变量。Java语言提供了volatile,在某些情况下比锁要更加方便。

volatile在多处理器开发中保证了共享变量的“ 可见性”。可见性的意思是当一个线程修改一个共享变量时,另外一个线程能读到这个修改的值。
内存分布
在这里插入图片描述

变量存储在主内存中,每个线程拥有自己的工作内存用来存放变量的拷贝,线程的读写操作是在各自的工作内存中进行的,操作的对象都是变量的拷贝,操作完毕后在刷新到主内存。

volatile变量是一种稍弱的同步机制在访问volatile变量时不会执行加锁操作,因此也就不会使执行线程阻塞,因此

volatile变量是一种比synchronized关键字更轻量级的同步机制。读取快 修改慢

* 1.volatile保证可见性

  • 1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。

  • 2)禁止进行指令重排序。

  • 编译出来的只有一条字节码指令,也不意味执行这条指令就是一个原子操作 一条字节码指令在解释

  • 执行时,解释器将要运行许多行代码才能实现。

* 什么是指令重排?

  • 指令重排是指JVM在编译Java代码的时候,或者CPU在执行JVM字节码的时候,对现有的指令顺序进行重新排序。

  • 指令重排的目的是为了在不改变程序执行结果的前提下,优化程序的运行效率。需要注意的是,这里所说的不改变执行结果, 指的是不改变单线程下的程序执行的结果。

注:单线程不改变过最终状态的情况下,会指令重排改变字节码指令的执行顺序。

* 如何使用volatile呢

运算结果并不依赖变量的当前值

或者能够确保只有单一的线程修改变量的值

注:非原子操作加锁 ,
例如: ++ 不能保证原子性,多线程下执行需要加synchronized 或者lock

作用

1.如果一个字段被声明成 volatile,java 线程内存模型确保所有线程看到这个变量的值是一致的。
2.禁止指令重排序。(jdk5 或更高版本)
它比 synchronized 的使用和执行成本会更低,因为它不会引起线程上下文的切换和调度。

volatile 实现原理

volatile 是基于 Memory Barrier 实现的。如果一个变量是 volatile 修饰的,JMM 会在写入这个字段之后插进一个 Write-Barrier 指令,并在读这个字段之前插入一个 Read-Barrier 指令。
Write-Barrier(写入屏障)将刷出所有在 Barrier 之前写入 cache 的数据,因此,任何 CPU 上的线程都能读取到这些数据的最新版本。
底层基于 C++的 volatile 实现,因为 volatile 自带了编译器屏障的功能,总能拿到内存中的最新值。
volatile 修饰的变量进行写操作的时候会多了一行下面的汇编代码。
在这里插入图片描述

lock 前缀指令的作用有两个:

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值