004.聊聊线程安全2

5 篇文章 0 订阅
5 篇文章 0 订阅

第二期里从线程安全的角度聊了聊系统设计
本期继续结合具体的技术点来聊聊线程安全

惯例,先看栗子

++i 或者 i++ 是否原子操作?

这里先不进行分析,大家可以先想想
我们先来看看Java的内存模型

Java能够实现跨平台,得益于Java虚拟机规范所定义的Java内存模型
这个模型屏蔽对硬件和操作系统的内存访问差异,使得Java程序在各个平台里运行都能够达到一致的内存访问效果
《深入Java虚拟机》

我们先具体看一下Java内存模型
这里写图片描述
通过上图可以很好的理解Java内存模型是怎样的

Java内存模型的主要目标是定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量这样的细节
《深入Java虚拟机》

共享变量存储在主内存里,如何从主内存读取变量,从本地内存写回到主内存
就是JMM所负责的事情了,其定义好这个变量的访问规则

本地内存也叫作工作内存
每个线程都有自己的工作内存,线程对变量的所有操作(读取、赋值等)都必须在工作内存中进行,不能直接读写主内存的变量

JMM定义了8种操作来完成主内存与工作内存之间的交互
这些操作在虚拟机实现时必须保证是原子的、不可再分的
lock、unlock、read、load、use、assign、store、write

比如:从主内存读取变量:
1.要先read,从主内存传输变量值到工作内存
2.执行load,把read操作的变量值放入工作内存变量副本中

从工作内存写入主内存:
1.要先store,把工作内存的变量值传输到主内存
2.执行write,把store操作的变量值放入主内存的变量中

read、load必须同时出现,同样,store、write必须同时出现

看完Java内存模型,再来了解下Java虚拟机字节码执行引擎
Java执行引擎的实现需要保证JMM及其所指定的规则

我们的JVM是基于栈的执行引擎,基于栈的指令集解释器

运行过程中,会保存方法调用执行的数据,这个存储的数据结构叫栈帧
栈帧保存了方法的局部变量表、操作数栈、动态链接和方法返回地址
方法执行与结束也就会对应着栈帧在虚拟机栈里的入栈和出栈
这里写图片描述
每个线程会有自己的线程栈,也可以理解为线程自己的工作空间
执行引擎运行过程,对于当前线程,只有位于栈顶的栈帧才是有效的,称为当前栈帧,相关联的方法是当前方法

执行过程,通过局部变量表来存储方法入参和方法内部局部变量的数据
一些计算和参数传递则通过操作数栈来进行

下面我们回到开头提到的例子
简单地写段代码,然后从JMM和字节码解释执行的角度来具体分析下
代码里定义了一个全局共享变量和一个局部变量
这里写图片描述

JDK1.8下编译得到的字节码
使用命令 javap -c class文件 得到如下的字节码
这里写图片描述

我们来具体看看main方法里的逻辑
这里写图片描述
对于全局变量a,我们可以看到首先是先获取变量的值,执行字节码 getstatic
然后放入栈中,并跟栈中的数值1 进行加操作然后把结果再入栈
最后把结果写回变量里

回到我们的内存模型,分为主内存和工作内存
再这里可以看到,要对变量a进行自增操作需要先获取a的值
放到线程栈里,然后再把执行自增操作的结果写回到变量a中
Java代码里对应的是 a++ 操作
后面的++a操作也是一样的字节码逻辑

而后面对变量b 的自增操作,我们可以看到有明显的不同
这里写图片描述
把数值0入栈,并放到局部变量表里的变量1中
然后直接进行自增操作
并没有像变量a 那样有变量的读写操作

回到变量a的自增操作字节码逻辑里
比如线程A 执行字节码 getstatic ,获取到变量a的值后,进行处理
此时,可能线程B 执行 putstatic ,对变量a进行写操作
则线程A 里的变量a 的值是脏的了

而变量b的自增操作则不会受到这样的影响,因为自始至终都在线程栈中执行的

PS:更加严谨的方法其实应该是对汇编代码进行分析,这里字节码已经足够说明问题了

如果我们对变量a 添加volatile属性,能不能保证线程安全呢?
这里写图片描述

我们看下字节码:
这里写图片描述

从字节码角度还是一样的,并没有变化

那么用volatile 给我们带来了什么?
有时间可以再好好学习研究下

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值