IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> volatile关键字 -> 正文阅读

[Java知识库]volatile关键字

当声明共享变量为volatile后,对这个变量的读/写将会很特别。那么它到底起着怎样的作用呢?

前言:

volatile是Java提供的一种轻量级的同步机制。Java语言包含俩种内在的同步机制:同步块(或同步方法)和volatile变量,相比于synchronized(synchronized通常称为重量级锁),volatile更轻量级,因为它不会引起线程上下文的切换和调度。

1.JMM的三大特征

JAVA内存模型的三个特征:

1.原子性:

一个操作不能被打断,要么全部执行完毕,要么不执行。在这点上有点类似于事务操作,要么全部执行成功,要么回退到执行该操作之前的状态。

2.可见性:

可见性指的是线程之间的可见性,一个线程修改的状态对另外一个线程是可见的。也就是一个线程对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后的写入。
其实之所以要保证可见性,主要与Java的内存模型有关。

内存模型
每个线程在执行的时候,会从主内存中拷贝一份到自己的本地内存,线程操作的时候是操作自己本地内存的变量,这样每个线程都操作自己本地内存的变量,就可能导致这个共享变量的数据不一致,这就体现了volatile的作用了。volatile可以使得一个线程操作共享变量的时候,能读到这个共享变量最新的变化,在这个变化上操作。

示意图


线程对共享变量的所有操作都必须在??的本地内存中进?,不能直接从主内存中读取。JMM通过控制主内存与每个线程的本地内存之间的交互,来提供内存可?性保证。

3.有序性:

对于一个线程的代码而言,我们总是以为代码的执行是从前往后的,依次执行的。这么说不能说完全不对,在单线程程序里,确实会这样执行;但是在多线程并发时,程序的执行就有可能出现乱序。用一句话可以总结为:在本线程内观察,操作都是有序的;如果在一个线程中观察另外一个线程,所有的操作都是无序的。前半句是指“线程内表现为串行语义(WithIn Thread As-if-Serial Semantics)”,后半句是指“指令重排”现象和“工作内存和主内存同步延迟”现象。

2.volatile关键字的特性:

? ? ? Java提供了两个关键字volatile和synchronized来保证多线程之间操作的有序性,volatile关键字本身通过加入内存屏障来禁止指令的重排序,而synchronized关键字通过一个变量在同一时间只允许有一个线程对其进行加锁的规则来实现,

当一个变量被volatile修饰时,会拥有两个特性:

  1. 保证了不同线程对该变量操作的内存可见性.(当一个线程修改了变量,其他使用次变量的线程可以立即知道这一修改).
  2. 禁止了指令重排序.

1.可见性

2.禁止指令重排序优化。
指令重排序是什么?简单点说就是jvm会把代码中没有依赖赋值的地方打乱执行顺序,由于一些规则限定,我们在单线程内观察不到打乱的现象(线程内表现为串行的语义),但是在并发程序中,从别的线程看另一个线程,操作是无序的。

volatile只可以用来修饰变量,不可以修饰方法和类:

一个非常经典的指令重排序例子:

public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {  
        synchronized (Singleton.class) {  
        if (singleton == null) {  
            singleton = new Singleton();  
        }  
        }  
    }  
    return singleton;  
    }  
}

这是很经典的双重锁校验实现的单例模式,想必很多人都看到过,代码中可能会被多个线程访问的singleton变量使用volatile修饰.我们看到singleton用了volatile修饰,由于 singleton= new SingletonTest();可分解为:

1.memory =allocate(); //分配对象的内存空间
2.ctorInstance(memory); //初始化对象
3.singleton=memory; //设置singleton指向刚分配的内存地址

操作2依赖1,但是操作3不依赖2,所以有可能出现1,3,2的顺序,当出现这种顺序的时候,虽然instance不为空,但是对象也有可能没有正确初始化,会出错

可参考:JMM概述_牧竹子的博客-CSDN博客_jmm

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-05-01 15:33:33  更:2022-05-01 15:37:22 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 2:06:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码