热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【Java猫说】Java多线程之内存可见性(上篇)

阅读本文约“3分钟”本文大致讲述两种线程实现的可见性,或许你已经提前想到了,那说明你的基础很好,我们要聊聊synchronized实现可见

阅读本文约“3分钟”


本文大致讲述两种线程实现的可见性,或许你已经提前想到了,那说明你的基础很好,我们要聊聊synchronized实现可见性与volatile实现可见性。

我们会谈及几个点:指令重排序、as-if-serial语义、volatile使用注意事项等

首先我们要了解下两个名词,有点术语的感觉,虽然我不喜欢那些专业名词,但是你懂得···

可见性:通俗的说就是一个线程对共享变量值的修改,可以及时地被其它线程看到
共享变量:即一个变量在多个线程的工作内存中存在副本,则这个变量就是这些线程的共享变量

这两个名称理解起来还不算难,对吧?那么我们来看看更加专业化的名词,我其实更希望有具象化的有趣的名词来代替,原谅我的文学水平有限。

Java内存模型(JMM)

Java Memory Model 描述了Java程序中各种变量(这里指线程共享变量,你已经理解上面的第二个名词了)的访问规则,以及在JVM中将变量存储到内存和从内存中读取出变量这样的底层细节,就像细胞要在血管中流动一样(一个不及格的比喻),它要求所有的变量都存储在主内存中,每个线程都有自己独立的工作内存,里面保存该线程使用到的变量的副本(也就是主内存中该变量的一份拷贝)

让我们来看看图型吧,文字有时理解起来比起图片要来的复杂,至少我是这样觉得,我更喜欢具象化的说明

图片描述

对于色调我一直有不同于别人的理解,原谅我看似混乱的搭配。

综合的总结一下,结合上图还有之前说的,我们可以定出一下两个原则(或许可以轻松一点的说,而不是用“原则”)

1、线程对共享变量的所有操作都必须在自己的工作空间(内存)中进行,不能直接从主内存中读写
2、不同线程之间无法直接访问其他线程中工作内存中的变量,线程间的变量值的传递需要通过主内存来完成

以上两句可能需要细细体会,就像你喝咖啡后不会立马喝下一口一样,请回味一下。

由此我们可以模糊但又明确的指出共享变量可见性实现的原理

结合下图一同说明下,线程A对共享变量的修改要想被线程B即使看到,需要经过如下两步:

1、把工作内存A中更新过的共享变量刷新到主内存中
2、将主内存中最新的共享变量的值更新到工作内存B中

图片描述

让我们重新回到主题,Java语言层面支持的可见性实现方式:
——synchronized
——volatile

而由以上的篇幅讲解你也知道了实现共享变量的可见性,需要保证两点:

1、线程修改后的共享变量值能够及时从其工作内存中刷新到主内存中
2、其他线程能够及时把共享变量的最新值从主内存更新到自己的工作内存中

synchronized可以实现在于它的性质:原子性(同步性)、可见性

JMM(看到这个单词时或许你应该想到前面的中文含义)关于synchronized有这样的一些规定:

1、线程解锁前,必须把共享变量的最新值刷新到主内存中
2、线程加锁时,将清空工作内存中共享变量的值,在使用共享变量时需要从主内存中重新读取最新的值
(需要注意的是,加锁与解锁需要同一把锁,这让我想到了Redis,你想到了什么呢?)

我们可精华的提升下,即线程解锁前对共享变量的修改在下次加锁时对其他线程是可见的

让我们大致看看线程执行互斥代码(即以上的描述)的过程:

1、获得互斥锁
2、清空工作内存
3、从主内存拷贝变量的最新副本到工作内存
4、执行代码
5、将更改后的共享变量的值刷新到主内存
6、释放互斥锁

(请自己思考一次,不要把5、6步的顺序颠倒了哦)

本文未完~,请期待下篇。
【Java猫说】Java多线程之内存可见性(下篇)
欢迎你留言讨论属于你的见解,毕竟每个人的味蕾都不一样,这杯咖啡有吸引到你吗?
(好像又是一个槽糕的比喻)


本文已转载个人技术公众号:UncleCatMySelf
欢迎留言讨论与点赞
上一篇推荐:【Java猫说】主数据类型和引用
下一篇推荐:【Java猫说】Java多线程之内存可见性(下篇)



推荐阅读
  • 本文回顾了作者在求职阿里和腾讯实习生过程中,从最初的迷茫到最后成功获得Offer的心路历程。文中不仅分享了个人的面试经历,还提供了宝贵的面试准备建议和技巧。 ... [详细]
  • 春季职场跃迁指南:如何高效利用金三银四跳槽季
    随着每年的‘金三银四’跳槽高峰期的到来,许多职场人士都开始考虑是否应该寻找新的职业机会。本文将探讨如何制定有效的职业规划、撰写吸引人的简历以及掌握面试技巧,助您在这关键时期成功实现职场跃迁。 ... [详细]
  • 2023年,Android开发前景如何?25岁还能转行吗?
    近期,关于Android开发行业的讨论在多个平台上热度不减,许多人担忧其未来发展。本文将探讨当前Android开发市场的现状、薪资水平及职业选择建议。 ... [详细]
  • 本文探讨了Java中线程的多种终止方式及其状态转换,提供了关于如何安全有效地终止线程的指导。 ... [详细]
  • 深入探讨:Actor模型如何解决并发与分布式计算难题
    在现代软件开发中,高并发和分布式系统的设计面临着诸多挑战。本文基于Akka最新文档,详细探讨了Actor模型如何有效地解决这些挑战,并提供了对并发和分布式计算的新视角。 ... [详细]
  • Java中的引用类型详解
    本文详细介绍了Java中的引用类型,包括强引用、软引用、弱引用和虚引用的特点和应用场景。 ... [详细]
  • 本文详细介绍了 Java 网站开发的相关资源和步骤,包括常用网站、开发环境和框架选择。 ... [详细]
  • 一家位于长沙的知名网络安全企业,现面向全国诚聘高级后端开发工程师,特别欢迎具有一线城市经验的技术精英回归故乡,共创辉煌。 ... [详细]
  • 深入解析JVM中的垃圾回收机制
    本文详细探讨了JVM中垃圾回收的几种主要算法及其工作原理,包括标记-清除、复制、标记-整理及分代收集算法,并简要介绍了常见的垃圾收集器。 ... [详细]
  • 本文详细介绍了Android系统的四层架构,包括应用程序层、应用框架层、库与Android运行时层以及Linux内核层,并提供了如何关闭Android系统的步骤。 ... [详细]
  • 在Java开发中,保护代码安全是一个重要的课题。由于Java字节码容易被反编译,因此使用代码混淆工具如ProGuard变得尤为重要。本文将详细介绍如何使用ProGuard进行代码混淆,以及其基本原理和常见问题。 ... [详细]
  • 阿里面试题解析:分库分表后的无限扩容瓶颈与解决方案
    本文探讨了在分布式系统中,分库分表后的无限扩容问题及其解决方案。通过分析不同阶段的服务架构演变,提出了单元化作为解决数据库连接数过多的有效方法。 ... [详细]
  • 深入解析Java中的空指针异常及其预防策略
    空指针异常(NullPointerException,简称NPE)是Java编程中最常见的异常之一。尽管其成因显而易见,但开发人员往往容易忽视或未能及时采取措施。本文将详细介绍如何有效避免空指针异常,帮助开发者提升代码质量。 ... [详细]
  • 面试题总结_2019年全网最热门的123个Java并发面试题总结
    面试题总结_2019年全网最热门的123个Java并发面试题总结 ... [详细]
  • 本文总结了Java初学者需要掌握的六大核心知识点,帮助你更好地理解和应用Java编程。无论你是刚刚入门还是希望巩固基础,这些知识点都是必不可少的。 ... [详细]
author-avatar
a403441305
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有