Java并发编程系列之三:Java内存模型

引言

在我们日常项目开发工作中,对于并发场景中经常出现的神奇的Bug大都是由于并发编程中的三个核心问题的不深入理解导致的,即如何进行高效的线程任务分配,如何有效的进行线程之间的相互协作以及如何保证在同一时刻只有一个线程进行共享变量的访问。那我们该如何解决并发编程这三座大山呢,这就需要我们对于Java的内存模型有着深入的理解。本文主要从以下几个方面来阐述Java的内存模型,希望对于学习并发编程的童鞋有所裨益。

  • 并发编程三大特性说明
  • volatile关键字说明
  • Java内存模型
  • 总结

一、并发编程三大特性说明

1、原子性

所谓原子性操作,就是类似数据库的事务操作,对应的一个操作或者多个操作,要么全部完成,要么全都失败。所有的操作不会被外界因素打断。

2、可见性

所谓可见性特性,就是当多个线程访问同一个变量时,如果一个线程修改了该值。其他线程也可以立马看到被修改后的变量的值。Javavolatile关键字保证了变量的可见性。当变量被volatile关键字修饰后,只要有线程修改了该变量值时,修改后的值会被立即刷新到主存中。其他线程进行共享变量读取时,会从主存中进行数据读取。如下图所示:
在这里插入图片描述

3、有序性

所谓有序性,是指在操作系统中程序的执行顺序和编写的代码的顺序是一致的。但是在Java内存模型中,为了提升运行效率是允许编译器和处理器对指令进行重排序的,但是不影响单线程运行的最终结果。

二、volatile关键字说明

volatile关键字可以保证多线程环境下的变量可见性,但是无法保证多线程操作的原子性。当volatile关键字修饰共享变量进行写操作时,在其对应的汇编代码中会存在以Lock为前缀的指令信息,改指令会促使处理器将缓存回写到内存中,所以说该变量具有以下两种特性:
(1)变量具备可见性特征,当一个线程对其进行修改后,其他线程可以读到期修改后的值,也就是说它会告诉编译器,对修饰变量的读写不实用CPU的缓存,而是在主存中进行读取和写入;
(2)禁止进行指令重排序;
所谓指令重排序,就是计算机为了提高系统的执行效率,会对计算机指令进行重排序的操作:
a、编译器重排序,即编译器在不改变单线程的程序予以的情况下,重新编排程序语句的执行顺序;
b、处理器重排序,如果程序代码中对于数据的前后依赖不敏感,处理器可以改变程序语句对应的机器码的执行顺序。

volatile关键字相对于synchronized关键字会显得轻一点,在某些场合可以替代synchronized关键字。

三、Java内存模型

我们知道在Java技术体系中,它是采用内存共享的模式来实现不同线程之间的信息通信。Java内存模型与硬件内存架构存在一定的映射关系

在这里插入图片描述
happens-beforeJMM中非常重要的一个原则,通过它来判断数据是否存在竞争、线程是否安全的重要依据。那到底什么是happens-before原则呢,网上的解释各有各的说法,按照自己的理解就是前面的一个操作的结果对于后续的操作来说是可见的。

四、总结

Java内存模型是我么理解并发编程的关键,也是编发编程的内功。本文通过三大特性的说明、volatile关键字的简单介绍以及JMM和物理架构的映射来简单阐述了Java内存模型。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

慕枫技术笔记

您的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值