热门标签 | 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多线程之内存可见性(下篇)



推荐阅读
  • 一次上线事故,30岁+的程序员踩坑经验之谈
    本文主要介绍了一位30岁+的程序员在一次上线事故中踩坑的经验之谈。文章提到了在双十一活动期间,作为一个在线医疗项目,他们进行了优惠折扣活动的升级改造。然而,在上线前的最后一天,由于大量数据请求,导致部分接口出现问题。作者通过部署两台opentsdb来解决问题,但读数据的opentsdb仍然经常假死。作者只能查询最近24小时的数据。这次事故给他带来了很多教训和经验。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • 2021最新总结网易/腾讯/CVTE/字节面经分享(附答案解析)
    本文分享作者在2021年面试网易、腾讯、CVTE和字节等大型互联网企业的经历和问题,包括稳定性设计、数据库优化、分布式锁的设计等内容。同时提供了大厂最新面试真题笔记,并附带答案解析。 ... [详细]
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
  • Java 11相对于Java 8,OptaPlanner性能提升有多大?
    本文通过基准测试比较了Java 11和Java 8对OptaPlanner的性能提升。测试结果表明,在相同的硬件环境下,Java 11相对于Java 8在垃圾回收方面表现更好,从而提升了OptaPlanner的性能。 ... [详细]
  • Java和JavaScript是什么关系?java跟javaScript都是编程语言,只是java跟javaScript没有什么太大关系,一个是脚本语言(前端语言),一个是面向对象 ... [详细]
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了软件测试知识点之数据库压力测试方法小结相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 本文介绍了Java虚拟机中的垃圾收集器,包括年轻代收集器Serial收集器、ParNew收集器、Parallel Scavenge收集器,以及老年代收集器Serial Old收集器、Parallel Old收集器和CMS收集器。对每种收集器的算法和特点进行了详细解析,希望对读者有参考价值。 ... [详细]
  • HashMap的相关问题及其底层数据结构和操作流程
    本文介绍了关于HashMap的相关问题,包括其底层数据结构、JDK1.7和JDK1.8的差异、红黑树的使用、扩容和树化的条件、退化为链表的情况、索引的计算方法、hashcode和hash()方法的作用、数组容量的选择、Put方法的流程以及并发问题下的操作。文章还提到了扩容死链和数据错乱的问题,并探讨了key的设计要求。对于对Java面试中的HashMap问题感兴趣的读者,本文将为您提供一些有用的技术和经验。 ... [详细]
  • Servlet多用户登录时HttpSession会话信息覆盖问题的解决方案
    本文讨论了在Servlet多用户登录时可能出现的HttpSession会话信息覆盖问题,并提供了解决方案。通过分析JSESSIONID的作用机制和编码方式,我们可以得出每个HttpSession对象都是通过客户端发送的唯一JSESSIONID来识别的,因此无需担心会话信息被覆盖的问题。需要注意的是,本文讨论的是多个客户端级别上的多用户登录,而非同一个浏览器级别上的多用户登录。 ... [详细]
  • 开发笔记:Python之路第一篇:初识Python
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Python之路第一篇:初识Python相关的知识,希望对你有一定的参考价值。Python简介& ... [详细]
  • Java编程思想一书中第21章并发中关于线程间协作的一节中有个关于汽车打蜡与抛光的小例子(原书的704页)。这个例子主要展示的是两个线程如何通过wait ... [详细]
  • 初识java关于JDK、JRE、JVM 了解一下 ... [详细]
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社区 版权所有