返回顶部
首页 > 资讯 > 后端开发 > Python >JavaVolatile关键字你真的了解吗
  • 874
分享到

JavaVolatile关键字你真的了解吗

2024-04-02 19:04:59 874人浏览 独家记忆

Python 官方文档:入门教程 => 点击学习

摘要

目录正文并发编程的三要素1.原子性2.可见性3.有序性VolatileVolatile 的内存模型Volatile 的实现原理(1) lock(2) unclock(3) read(

正文

在谈 Volatile 之前,我们先回顾下 Java 内存模型 的三要素:原子性、可见性、有序性,也就是大家常提到的并发编程三要素。

并发编程的三要素

1.原子性

数据库事务中的原子性一样,满足原子性特性的操作是不可中断的,要么全部执行成功要么全部执行失败。

只有简单的读取、赋值(而且必须是将数字赋值给某个变量,变量之间的相互赋值不是原子操作)才是原子操作。

比如:

i = 2;j = i;i++;i = i + 1;

上面4个操作中,i=2是读取操作,必定是原子性操作,j=i你以为是原子性操作,其实吧,分为两步,一是读取i的值,然后再赋值给j,这就是2步操作了,称不上原子操作,i++和i = i + 1其实是等效的,读取i的值,加1,再写回主存,那就是3步操作了。

所以上面的举例中,最后的值可能出现多种情况,就是因为满足不了原子性。

非原子操作都会存在线程安全问题,需要我们使用同步技术(sychronized)来让它变成一个原子操作,java的concurrent包下提供了一些原子类:比如:AtomicIntegerAtomicLong等。

2.可见性

多个线程访问同一个共享变量时,其中一个线程对这个共享变量值的修改,其他线程能够立刻获得修改以后的值。

3.有序性

编译器和处理器为了优化程序性能而对指令序列进行重排序,也就是你编写的代码顺序和最终执行的指令顺序是不一致的。但是重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。

Volatile

Volatile 是一个Java语言的类型修饰符,一旦一个共享变量(类的成员变量、类的静态成员变量)被Volatile修饰之后,那么就具备了两层语义:

1、保证多线程下的可见性

2、禁止进行指令重排序(即保证有序性)

这里需要注意一个问题,Volatile 只能让被他修饰内容具有可见性、有序性 。Volatile只能保证对单次读/写的原子性,i++ 这种操作不能保证原子性。

Volatile 的内存模型

Volatile 的内存模型

**Java 内存模型(JMM)**是一种抽象的概念,并不真实存在,它描述了一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段、静态字段和构成数组对象的元素)的访问方式。

试图屏蔽各种硬件和操作系统的内存访问差异,以实现让 Java 程序在各种平台下都能达到一致的内存访问效果。

Java内存模型规定了所有的变量都存储在主内存中,每条线程还有自己的工作内存,线程的工作内存中保存了该线程中是用到的变量的主内存副本拷贝,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存。不同的线程之间也无法直接访问对方工作内存中的变量,线程间变量的传递均需要自己的工作内存和主存之间进行数据同步进行。

  • 主内存 主要存储的是Java实例对象,所有线程创建的实例对象都存放在主内存中,不管该实例对象是成员变量还是方法中的本地变量(也称局部变量),当然也包括了共享的类信息、常量、静态变量。由于是共享数据区域,多条线程对同一个变量进行访问可能会发现线程安全问题。
  • 工作内存 每条线程都有自己的工作内存(Working Memory,又称本地内存,可与前面介绍的处理器高速缓存类比),线程的工作内存中保存了该线程使用到的变量的主内存中的共享变量的副本拷贝。

工作内存是 JMM 的一个抽象概念,并不真实存在 。它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化。

主要存储当前方法的所有本地变量信息(工作内存中存储着主内存中的变量副本拷贝),每个线程只能访问自己的工作内存,即线程中的本地变量对其它线程是不可见的,就算是两个线程执行的是同一段代码,它们也会各自在自己的工作内存中创建属于当前线程的本地变量,当然也包括了字节码行号指示器、相关Native方法的信息。

Volatile 的实现原理

Volatile 保证内存可见性

Volatile 的实现原理

主内存和工作内存之间的交互有具体的交互协议,JMM定义了 八种操作 来完成,这八种操作是 原子的 、 不可再分的 ,它们分别是:lockunlockreadloaduseassignstorewrite

其中,lock , unlock , read , write 作用于主内存; load ,use , assign , store 作用于工作内存。

(1) lock

将主内存中的变量定,为一个线程所独占。

(2) unclock

将lock加的锁定解除,此时其它的线程可以有机会访问此变量。

(3) read

将主内存中的变量值读到工作内存当中。

(4) load

将read读取的值保存到工作内存中的变量副本中。

(5) use

将值传递给线程的代码执行引擎。

(6) assign

将执行引擎处理返回的值重新赋值给变量副本。

(7) store

将变量副本的值存储到主内存中。

(8) write

将 store 存储的值写入到主内存的共享变量当中。

  • 从主存复制变量到当前工作内存(read and load)
  • 执行代码,改变共享变量值 (use and assign)
  • 用工作内存数据刷新主存相关内容 (store and write)

指令规则

  • read 和 load、store 和 write 必须成对出现。
  • assign 操作,工作内存变量改变后必须刷回主内存。
  • 同一时间只能运行一个线程对变量进行 lock,当前线程 lock 可重入,unlock 次数必须等于 lock 的次数,该变量才能解锁。
  • 对一个变量 lock 后,会清空该线程工作内存变量的值,重新执行 load 或者 assign 操作初始化工作内存中变量的值。
  • unlock 前,必须将变量同步到主内存( store/write 操作)。

Volatile源码案例

Volatile源码案例

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注编程网的更多内容!

--结束END--

本文标题: JavaVolatile关键字你真的了解吗

本文链接: https://lsjlt.com/news/160500.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • JavaVolatile关键字你真的了解吗
    目录正文并发编程的三要素1.原子性2.可见性3.有序性VolatileVolatile 的内存模型Volatile 的实现原理(1) lock(2) unclock(3) read(...
    99+
    2024-04-02
  • 你真的了解 PHP 关键字 API 容器吗?
    PHP 是一种广泛使用的服务器端脚本语言,由于其易学易用的特性,它已经成为了众多 Web 开发者的首选语言。而在 PHP 中,有一些关键字,比如 API 和容器,它们在开发中也扮演着非常重要的角色。本文将详细介绍这两个关键字,帮助读者更好地...
    99+
    2023-10-25
    关键字 api 容器
  • 你真的了解Go中异步编程和数组的关键字吗?
    Go语言是一门高效的编程语言,它具有简洁明了的语法和强大的并发特性。其中异步编程和数组是Go语言中的两个重要关键字。本文将为大家详细介绍Go语言中异步编程和数组的关键字,并且演示代码方便大家理解。 一、异步编程 异步编程是指在程序执行过程中...
    99+
    2023-10-02
    数组 异步编程 关键字
  • 关于Java Object你真的了解了吗
    导读: 在平时的coding中hashCode()和equals()的使用的场景有哪些?clone深复制怎么实现?wait()和notify()有什么作用?finalize()方法干嘛的?看似coding中使用的不多,不重要,但是有没有跟我...
    99+
    2023-05-31
    java object ava
  • C/C++的关键字之static你了解吗
    目录C语言隐藏场景演示解决方法保持变量内容的持久默认初始化为0Cppstatic类成员变量static类成员方法单例模式总结C语言 隐藏 场景演示 当我们同时编译多个文件时,所有未加...
    99+
    2024-04-02
  • 关于@Autowierd && @Resource 你真的了解吗
    目录关于@Autowierd && @Resource 你真的了解吗1.@Autowierd2.@Resource2.1@Resource具体装配顺序,即指定的注入实...
    99+
    2024-04-02
  • 学习MySQL必须了解的13个关键字,你get了吗?
    目录 1、三范式 2、字符集 3、自定义变量 4、选择优化的数据类型 (1)更小的 (2)更简单的 (3)尽量避免NULL 5、视...
    99+
    2023-08-20
    数据库 mysql sql
  • ASP 缓存 重定向 关键字的使用技巧,你真的掌握了吗?
    ASP 缓存、重定向和关键字是 ASP.NET 中非常重要的概念,它们在提高网站性能和优化 SEO 方面起着至关重要的作用。在本文中,我们将介绍 ASP 缓存、重定向和关键字的使用技巧,帮助您更好地理解它们并掌握它们的用法。 ASP 缓存 ...
    99+
    2023-08-08
    缓存 重定向 关键字
  • Java中关于关键字使用的一些技巧,你了解吗?
    Java是一种高度常用的编程语言,其中关键字的使用在程序开发过程中起着至关重要的作用。本文将介绍一些Java中关于关键字使用的技巧,帮助读者更好地理解和运用Java编程语言。 一、final关键字的使用 在Java中,final关键字表示不...
    99+
    2023-07-09
    关键字 数组 开发技术
  • C++字符串类的封装你真的了解吗
    目录字符串类的封装常规代码头文件函数实现文件Test文件重载左移>>重载右移<<重载赋值=重载中括号[ ]重载加号+重载==总结字符串类的封装 常规代码 头文...
    99+
    2024-04-02
  • 你真的了解IP地址吗?
    本文已收录于专栏 ⭐️ 《计算机网络》⭐️ 学习指南: IP协议基本认识分类地址多播地址 无分类地址划分方式子网掩码 IP 分片与重组IPv6基本认识IPv4 首部与 ...
    99+
    2023-09-09
    tcp/ip 网络 服务器 网络协议 ip
  • 你真的需要了解Bash吗?
    Bash是一种强大的命令行解释器,它是Linux和macOS操作系统上的默认Shell。尽管它是如此重要,但很多人并不了解Bash的实际用途。在本文中,我们将探讨Bash的重要性以及它如何帮助我们更好地管理和控制计算机系统。 Bash是什么...
    99+
    2023-08-15
    path bash http
  • Java中的static关键字你了解多少
    目录一.static关键字的用途1)static方法2)static变量3)static代码块二.static关键字的误区1.static关键字会改变类中成员的访问权限吗?2.能通过...
    99+
    2024-04-02
  • 你对 Go 中的关键字了解多少?
    Go 是一门强类型、静态类型、编译型的编程语言,它在设计时强调了简洁、快速和安全。作为一个程序员,熟练掌握 Go 的关键字是非常重要的,因为它们是 Go 语言的基础。 package 在 Go 中,每个文件必须属于一个 package,...
    99+
    2023-08-18
    开发技术 数组 关键字
  • java的泛型你真的了解吗
    目录泛型的概述和优势自定义泛型类自定义泛型方法自定义泛型接口泛型通配符、上下限总结泛型的概述和优势 泛型概述 泛型:是JDK5中引入的特性,可以在编译阶段约束操作的数据类型,并进行检...
    99+
    2024-04-02
  • Vue的过滤器你真了解吗
    目录1.过滤器1.1对过滤器的理解1.2全局过滤器:1.3局部过滤器:1.4过滤器的案例总结1. 过滤器 案例中使用到时间格式相关API 1.1 对过滤器的理解 定义:对要显示的数据...
    99+
    2024-04-02
  • Java 缓存:你真的了解它吗?
    在 Java 开发中,缓存是一个非常重要的概念。它可以大大提升应用程序的性能,减少对底层资源的占用,提高用户体验。但是,你真的了解 Java 缓存吗?本文将为大家介绍 Java 缓存的基本概念、分类、应用场景以及常见的缓存框架。 一、缓存...
    99+
    2023-10-06
    缓存 学习笔记 面试
  • 内网穿透你真的了解吗?
    前言 内网穿透作为程序员常用的调试手段之一,我们可以通过在个人电脑上运行花生壳或者 frp 等方式,让他人访问我们本地启动的服务,而且这种访问可以不受局域网的限制,当我们使用ngrok,frp等开源框架时,你是否有好奇过它神奇的作用?明明没...
    99+
    2023-08-31
    网络穿透 NAT 内网 后端开发 Linux服务器开发
  • 带你了解Java中Static关键字的用法
    目录Java中Static关键字的一些用法详解1. Static 修饰类属性,因为静态成员变量可以通过类名+属性名调用,非静态成员变量不能通过类名+属性名调用;2. Static 修...
    99+
    2024-04-02
  • C++的运算符你真的了解吗
    目录前言1 算术运算符2 赋值运算符3 比较运算符4 逻辑运算符总结前言 运算符的作用:用于执行代码的运算 主要有: 1 算术运算符 用于处理四则运算 对于前置递增:将递增运算前...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作