java赋值语句_java并发编程之原子性问题

程序是否线程安全,取决于哪些要素呢,主要是以下三个:

原子性,

可见性,

有序性。

今天先一起来学习原子性。

原子性:

我理解一个操作不可再分,即为原子性。而在并发编程的环境中,原子性的含义就是只要该线程开始执行这一系列操作,要么全部执行,要么全部未执行,不允许存在执行一半的情况。

老生常谈的银行转账情况用于理解(仅限于理解,真实的银行转账没这么简单):

A账户向B账户转钱,A账户转出1万元,银行就必须保证B账户收到1万元,即使有问题,也必须保证是A账户转出失败,钱还在A账户。不然A账户转了,B账户却没收到,银行的操作就不是原子性的,客户的利益受到损失。

谈及原子性问题,需要先了解Java内存模型的基本情况:

为了执行效率,java的内存被划分为工作内存与主内存(可类比为计算机的高速缓存与内存),如下图所示:

a8bb0bd1c5fd391067a227b73ee14120.png

线程与工作内存和主内存

工作内存中,放着线程使用的主内存的拷贝。线程对变量的操作必须通过工作内存进行,而不能直接访问主内存,工作内存直接相互独立。

内存模型中,还定义了八种原子的操作指令,供程序使用,如下所示:

-----内容参考:《深入理解java虚拟机》----begin

lock(锁定):作用于主内存,它把一个变量标记为一条线程独占状态;

read(读取):作用于主内存,它把变量值从主内存传送到线程的工作内存中,以便随后的load动作使用;

load(载入):作用于工作内存,它把read操作的值放入工作内存中的变量副本中;

use(使用):作用于工作内存,它把工作内存中的值传递给执行引擎,每当虚拟机遇到一个需要使用这个变量的指令时候,将会执行这个动作;

assign(赋值):作用于工作内存,它把从执行引擎获取的值赋值给工作内存中的变量,每当虚拟机遇到一个给变量赋值的指令时候,执行该操作;

store(存储):作用于工作内存,它把工作内存中的一个变量传送给主内存中,以备随后的write操作使用;

write(写入):作用于主内存,它把store传送值放到主内存中的变量中。

unlock(解锁):作用于主内存,它将一个处于锁定状态的变量释放出来,释放后的变量才能够被其他线程锁定;

Java内存模型还规定了执行上述8种基本操作时必须满足如下规则:

1、不允许read和load、store和write操作之一单独出现(即不允许一个变量从主存读取了但是工作内存不接受,或者从工作内存发起会写了但是主存不接受的情况),以上两个操作必须按顺序执行,但没有保证必须连续执行,也就是说,read与load之间、store与write之间是可插入其他指令的。

2、不允许一个线程丢弃它的最近的assign操作,即变量在工作内存中改变了之后必须把该变化同步回主内存。

3、不允许一个线程无原因地(没有发生过任何assign操作)把数据从线程的工作内存同步回主内存中。

4、一个新的变量只能从主内存中“诞生”,不允许在工作内存中直接使用一个未被初始化(load或assign)的变量,换句话说就是对一个变量实施use和store操作之前,必须先执行过了assign和load操作。

5、一个变量在同一个时刻只允许一条线程对其执行lock操作,但lock操作可以被同一个条线程重复执行多次,多次执行lock后,只有执行相同次数的unlock操作,变量才会被解锁。

6、如果对一个变量执行lock操作,将会清空工作内存中此变量的值,在执行引擎使用这个变量前,需要重新执行load或assign操作初始化变量的值。

7、如果一个变量实现没有被lock操作锁定,则不允许对它执行unlock操作,也不允许去unlock一个被其他线程锁定的变量。

8、对一个变量执行unlock操作之前,必须先把此变量同步回主内存(执行store和write操作)。

-----内容参考:《深入理解java虚拟机》----end

因此我们写了一个程序,就很容易判断是否是具备原子性的,如下所示:

int x = 10; //语句1

long y=100;//语句2

int z = x; //语句3

x++; //语句4

z = z + 1; //语句5

volatile int a=0;

a=x;//语句6

语句1:只执行了assign语句,将10赋给工作内存中的x,原子的。

语句2:由于long类型为64位的,java可能会出现写两次32位数据到工作内存的情况,导致操作是非原子的(几乎所有虚拟机都对这种操作进行了封装,使其变为和原子操作)

语句3:use获取x的值,再assign赋值给z,非原子的。

语句4:user获取x的值,加1,在assign赋值给x,非原子的。

语句5:user获取z的值,加1,在assign赋值给z,非原子的。

语句6:use获取x的值,assign赋值给a,并且马上store将a的新值存储到主内存中,并将其他工作线程中的a值失效,非原子的。 如果其他线程要获取a的值,需要对应的工作内存重新从主内存中获取(volatile的可见性原理)。

感兴趣的小伙伴欢迎关注我的公众号:暖爸的java家园

8caffd4cacd6cc7281b95845a1752383.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/297387.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

“高阶思维”发展意识

1. 前言这个题目不太好交流,因为每个人的认知层面不同,不好达成大多数人趋近相同的看法。这个题目高度抽象化,不谈具体化的内容显得空洞及不容易理解,谈具体化的内容又无法找到着力点。抽象能力本身就是高阶思维的一种体现形式&a…

SQL Server返回当前实例系统日期和时间的函数

下面列举出SQL Server返回实例系统日期和时间的函数,除了ANSI标准函数CURRENT_TIMESTAMP在应用时无需在函数后多加一对空的小括号"()"外,其余均需。 从返回的数据类型"DATETIME2"就可以知道,后面三个函数是SQL Server 20…

培养沙雕要从娃娃抓起

1 培养沙雕要从娃娃抓起▼2 好了好了你们两个可以去洗发店门口上班了▼3 毛绒版俄罗斯方块纵享丝滑▼4 我还以为会有令人期待的被打环节▼5 小蜘蛛你好我是唐僧,请问我可以跟你回盘丝洞吗▼6 吃冰淇淋讲究直接上手▼7 在等奶茶的美团小哥我也想像他一样出门荡…

详解Ubuntu for Android:Thin Client

原文地址:http://blog.csdn.net/ce123/article/details/7291445 详解Ubuntu for Android:Thin Client 一、Ubuntu for Android的定义 在移动终端性能日益强大、多核处理器基本普及的现在,将通用的Ubuntu操作系统与Android系统进行亲密的整合&…

Dapr + .NET 实战(九)本地调试

前几节开发Dapr应用程序时,我们使用 dapr cli 来启动dapr服务,就像这样:dapr run --dapr-http-port 3501 --app-port 5001 --app-id frontend dotnet .\FrontEnd\bin\Debug\net5.0\FrontEnd.dll如果你想要通过dapr调试服务呢?在…

javadoc文档的生成方法_[springboot 开发单体web shop] 4. Swagger生成Javadoc

Swagger生成JavaDoc在日常的工作中,特别是现在前后端分离模式之下,接口的提供造成了我们前后端开发人员的沟通成本大量提升,因为沟通不到位,不及时而造成的[撕币]事件都成了日常工作。特别是很多的开发人员不擅长沟通,…

15个IT技术人员必须思考的问题

行内的人自嘲是程序猿、屌丝和码农,行外的人也经常拿 IT 人调侃,那么究竟是 IT 人没有价值,还是没有仔细思考过自身的价值? 1. 搞 IT 的是屌丝、码农、程序猿? 人们提到 IT 人的时候,总会想到他们呆板、不解…

mysql innodb表损坏_MySQL数据库INNODB表损坏修复处理过程分享

##状况描述突然收到MySQL报警,从库的数据库挂了,一直在不停的重启,打开错误日志,发现有张表坏了。innodb表损坏不能通过repair table 等修复myisam的命令操作。现在记录下解决过程,下次遇到就不会这么手忙脚乱了。处理…

20幅扎心漫画,道尽无数人的人生!30万网友:这简直是在偷窥我生活...

全世界只有3.14 % 的人关注了爆炸吧知识每个人在这世界上都是独特的个体但我们常常在很多方面把生活过得很类似在ins上,名叫Sanesparza的博主就把生活中的各种细节通过漫画的形式表达引来31万网友围观许多人纷纷表示:这不就是我吗!太扎心了&a…

多种方法解决Exchange 2010 EMC批量启用邮箱之后出..

平时大家在做Exchange 项目的时候都是需要批量导入AD账户和批量启用AD账户的邮箱,但是有一个比较奇怪的问题是当你使用Exchange 2010 EMC来批量启用邮箱之后会出现乱码问题,并且邮箱用户不能发送和接收电子邮件,那么该如何处理乱码问题呢?不要着急,其实有3种方法可以处理Excha…

matlab菲涅尔衍射_有问必答——SYNOPSYS安装体验课堂——可以设计菲涅尔透镜吗?...

问:SYNOPSYS可以设计菲涅尔透镜吗?答:在USS中有多种菲涅尔面型,用户输入参数即可。问:SYNOPSYS中具有的输入方式?答:大家总是有个误区,以为SYNOPSYS需要输入命令运行,其实…

WeakReference reference quene GC

在了解WeakReference之前,先给出一段简单的代码: public class WeakReferenceTest {public static void main(String[] args) throws Exception {Object o new Object();// 默认的构造函数&#xff0c;会使用ReferenceQueue.NULL 作为queueWeakReference<Object> wr ne…

北大4位数学天才,如今齐聚美国搞科研,令人叹息

全世界只有3.14 % 的人关注了爆炸吧知识最近这些年&#xff0c;计算机、电子产业异军突起&#xff0c;人工智能越来越受到追捧和重视&#xff0c;电子产品智能化已经成为发展的一种潮流和趋势。与此同时&#xff0c;国际竞争也日益激烈&#xff0c;这种竞争归根结底还是人才的竞…

为什么 Dapr 如此令人兴奋

如今你构建软件&#xff0c;您可以从数量众多的云服务中进行选择。仅 AWS 就每个月都在不断为其200多项服务添加新服务&#xff0c;而其他云提供商也都在跟上。如果您的公司想与您的竞争对手竞争&#xff0c;您就需要充分利用这些服务&#xff0c;这些服务在不同的云提供商都有…

java对象头_我的并发编程(二):java对象头以及synchronized升级过程

一、概述研究java对象头的目的是详细分析Java的synchronized锁的升级过程&#xff0c;因为synchronized在锁升级的时候&#xff0c;就是依赖对象头的信息来决定的。本博文针对64位的操作系统来对Java对象头进行详解。二、详细分析1. 用户态与内核态内核态与用户态是操作系统的两…

【转】Beagleboard:BeagleBoneBlack

原文网址&#xff1a;http://elinux.org/Beagleboard:BeagleBoneBlack Did you know that elinux.org has Mailing Lists? Please feel free to register today to discuss the wiki in general, request features, etc. etc.. Thanks!--Wmat (talk) Beagleboard:BeagleBoneBl…

剖析IE浏览器子系统的性能权重

来源于InfoQ&#xff1a; 微软IE开发团队性能主管Jason Weber在一篇博 文中介绍了IE浏览器的各个子系统&#xff0c;并通过实验数据展示了不同网站对浏览器子系统的性能影响和权重&#xff0c;InfoQ中文站对相关内容做了整理&#xff0c;希望对 浏览器开发人员和Web应用开发人员…

每年通过率仅1%的“天才考试”,中国到底应不应该学?

▲ 点击查看说起世界上最顶尖的基础教育&#xff0c;新加坡绝对能占一席之地。香港首富李嘉诚是这么评价新加坡教育的&#xff1a;“新加坡采用的教育体系源于英国传统的教育制度&#xff0c;它的私立、私立教育院校及一流大学和国际教育机构全球卓越。”李嘉诚甚至在长孙还没多…

C# VS生成后事件命令行

“ 引言部分&#xff0c;总领全篇文章的中心内容。”01—前言Visual Studio中&#xff0c;可以在项目-》属性-》生成事件-》生成后事件命令行&#xff08;O&#xff09;:中设置项目生成后执行的脚本&#xff0c;从而实现项目文件生产后的自动部署。如下图所示&#xff1a;02—自…

mysql binlog 大数据_后起之秀 | MySQL Binlog增量同步工具go-mysql-transfer实现详解

一、 概述工作需要研究了下阿里开源的MySQL Binlog增量订阅消费组件canal&#xff0c;其功能强大、运行稳定&#xff0c;但是有些方面不是太符合需求&#xff0c;主要有如下三点&#xff1a;需要自己编写客户端来消费canal解析到的数据server-client模式&#xff0c;需要同时部…