首页 > 编程语言 >[深入理解Java虚拟机]原子性/可见性/有序性

[深入理解Java虚拟机]原子性/可见性/有序性

时间:2024-07-26 12:40:22浏览次数:16  
标签:Java 变量 虚拟机 线程 内存 有序性 volatile

原子性、可见性与有序性

Java内存模型是围绕着在并发过程中如何处理原子性、可见性和有序性这三个特征来建立的,我们逐个来看一下哪些操作实现了这三个特性。

  1. 原子性(Atomicity)

由Java内存模型来直接保证的原子性变量操作包括read、load、assign、use、store和write这六个, 我们大致可以认为,基本数据类型的访问、读写都是具备原子性的(例外就是long和double的非原子性协定,读者只要知道这件事情就可以了,无须太过在意这些几乎不会发生的例外情况)。 如果应用场景需要一个更大范围的原子性保证(经常会遇到),Java内存模型还提供了lock和 unlock操作来满足这种需求,尽管虚拟机未把lock和unlock操作直接开放给用户使用,但是却提供了更 高层次的字节码指令monitorenter和monitorexit来隐式地使用这两个操作。这两个字节码指令反映到Java 代码中就是同步块——synchronized关键字,因此在synchronized块之间的操作也具备原子性。

  1. 可见性(Visibility)

可见性就是指当一个线程修改了共享变量的值时,其他线程能够立即得知这个修改。

上文在讲解 volatile变量的时候我们已详细讨论过这一点。Java内存模型是通过在变量修改后将新值同步回主内存,在变量读取前从主内存刷新变量值这种依赖主内存作为传递媒介的方式来实现可见性的,无论是普通变量还是volatile变量都是如此。普通变量与volatile变量的区别是,volatile的特殊规则保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新。因此我们可以说volatile保证了多线程操作时变量的可见性,而普通变量则不能保证这一点。 除了volatile之外,Java还有两个关键字能实现可见性,它们是synchronizedfinal

同步块的可见性是由“对一个变量执行unlock操作之前,必须先把此变量同步回主内存中(执行store、write操 作)”这条规则获得的。

而final关键字的可见性是指:被final修饰的字段在构造器中一旦被初始化完成,并且构造器没有把“this”的引用传递出去(this引用逃逸是一件很危险的事情,其他线程有可能通 过这个引用访问到“初始化了一半”的对象),那么在其他线程中就能看见final字段的值。

如代码清单 12-7所示,变量i与j都具备可见性,它们无须同步就能被其他线程正确访问。

public static final int i;
public final int j;
static {
	i = 0; // 省略后续动作
}
{
	// 也可以选择在构造函数中初始化
	j = 0; // 省略后续动作 
}
  1. 有序性(Ordering)

Java内存模型的有序性在前面讲解volatile时也比较详细地讨论过了,Java程序中天然的有序性可以总结为一句话:如果在本线程内观察,所有的操作都是有序的;如果在一个线程中观察另一个线程, 所有的操作都是无序的。前半句是指线程内似表现为串行的语义(Within-Thread As-If-Serial Semantics),后半句是指“指令重排序”现象和“工作内存与主内存同步延迟”现象。 Java语言提供了volatile和synchronized两个关键字来保证线程之间操作的有序性,volatile关键字本 身就包含了禁止指令重排序的语义,而synchronized则是由“一个变量在同一个时刻只允许一条线程对 其进行lock操作”这条规则获得的,这个规则决定了持有同一个锁的两个同步块只能串行地进入。 介绍完并发中三种重要的特性,读者是否发现synchronized关键字在需要这三种特性的时候都可以 作为其中一种的解决方案?看起来很“万能”吧?的确,绝大部分并发控制操作都能使用synchronized来 完成。synchronized的“万能”也间接造就了它被程序员滥用的局面,越“万能”的并发控制,通常会伴随 着越大的性能影响。

标签:Java,变量,虚拟机,线程,内存,有序性,volatile
From: https://www.cnblogs.com/DCFV/p/18325066

相关文章

  • “Elasticsearch精英进阶:从零到精通的安装,从Kibana到Java API,全面掌握CRUD与DSL查询及
    目录引言1.初识elasticsearch1.1.认识和安装 1.1.1.安装elasticsearch 1.1.2.安装Kibana 1.2.倒排索引1.2.1.正向索引1.2.2.倒排索引1.2.3.正向和倒排1.3.基础概念1.3.1.文档和字段1.3.2.索引和映射1.3.3.mysql与elasticsearch1.4.1.安装IK分词器1.4.2.使......
  • 安装虚拟机Ubuntu&配置SSH&配置samba&设置公钥
    1安装虚拟机及Ubuntu准备好Vmware16安装包和Ubuntu16.04安装包创建新的虚拟机选择自定义配置选择虚拟机硬件兼容性:默认下一步安装客户机操作系统:选择稍后安装操作系统选择客户机操作系统:选择Linux、Ubuntu64位命名虚拟机:自行修改,可默认下一步处理器配置:根据电脑配......
  • Web应用课 3.3 JavaScript——对象、数组、函数、类、事件
    对象英文名称:Object。类似于C++中的map,由key:value对构成。value可以是变量、数组、对象、函数等。函数定义中的this用来引用该函数的“拥有者”。eg.letperson={name:'zjq',age:18,money:100,friends:['yxc','Bob','Lucy'],//对象成员可以是数......
  • JavaScript操作BOM与DOM
    BOM操作window对象window对象是整个BOM的核心,表示浏览器打开的窗口。属性属性                              描述history     用户访问过的URL信息(历史记录)location        当前URL的信息。screen   ......
  • 【java SE语法篇】1. 运算符
    目录1.运算符和表达式2.算数运算符3.隐式转换4.强制转换5.自增自减运算符6.赋值运算符7.扩展运算符8.关系运算符9.逻辑运算符9.1&和|的使用:9.2^(异或)的使用:9.3!(取反)的使用:10.短路逻辑运算符11.三元运算符1.运算符和表达式运算符:就是对常量或者......
  • delphi调用Java类
    1、jdk的安装:https://www.cnblogs.com/ljk2008/p/18324820。2、jvm.dll:如果提示找不到JVM.dll需要在classpath、path中分别添加jvm.dll的路径。3、用到三方库:https://github.com/aleroot/DelphiJNI.git。4、JAVA类(CLASS、JAR)要放置在对应的文件夹内,如:packagecom.com1.com2;对......
  • OpenFeign报错:Caused by: java.lang.IllegalStateException: Method has too many Bod
    近两天在开发进行若依二开,openfeign需要一个微服务调用另一个微服务。等service层注入远程bean后,报错Causedby:java.lang.IllegalStateException:MethodhastoomanyBodyparameters:publicabstractvoidcom.shop.user.remote.RemoteUmsMemberAddressService.export(j......
  • Java NIO框架Netty教程(四)- ChannelBuffer
    在字符串消息收发中提到。ChannelBuffer是Netty中非常重要的概念。所有消息的收发都依赖于这个Buffer。我们通过Netty的官方的文档来了解一下,基于流的消息传递机制。Inastream-basedtransportsuchasTCP/IP,receiveddataisstoredintoasocketreceivebuffer.Unf......
  • Java NIO框架Netty教程(六)-Java NIO Selector模式
    全文详见个人独立博客:JavaNIO框架Netty教程(六)-JavaNIOSelector模式JavaNIO框架Netty教程(六)-JavaNIOSelector模式看到标题,您可能觉得,这跟Netty有什么关系呢?确实,如果你完全是使用Netty的,那么可能你可以完全不需要了解Selector。但是,不得不提的是,Netty底层关于NIO的实......
  • (Javaweb)Vue
    目录一.Vue概述二Vue指令三.vue生命周期一.Vue概述1.model--数据模型:包含了很多的业务数据以及数据的处理方法2.view--视图层--数据的展示--DOM元素3.viewmodel--完成数据绑定的核心,实现model与viewmodel之间的数据连接其中,MVVM由三部分组成,model,view,viewmodelm......