Java内存模型以及线程安全的可见性问题

探究Java内存模型与线程安全 Java 内存模型(Java Memory Model,简称 JMM)是一套规则,用于规定多线程环境下变量的可见性、有序性和原子性。简单来说,JMM 就是用来保证在多线程环境下,程序的行为符合预期。通过上面的例子,我们深入探讨了 Java 内存模型以及如何确保线程安全。使用volatile和等关键字和技术可以帮助我们有效地避免多线程环境下的数据不一致问题。 阅读详情

Java内存模型以及线程安全的可见性问题

1.Java内存模型 VS JVM运行时数据区

1.1定义

JAVA语言规范提出JAVA内存模型,JAVA内存模型是对多线程程序的一些归则。
JVM虚拟机规范提出JVM运行时数据区,JVM运行时数据区描述的是线程共享区域堆、方法区,线程独占区域虚拟机栈、本地方法栈、程序计数器。
在这里插入图片描述

1.2 多线程问题

在这里插入图片描述

1.3 多线程问题原因分析

1.cpu高速缓存导致,程序中在3s时间还存在值获取不到的情况,排除为cpu高速缓存导致,因为cpu缓存协议可保证在极短时间内数据的一致性。
在这里插入图片描述
在这里插入图片描述

  • cpu指令重排序导致
    指令重排:java编译器的指令重排和微处理器指令重排(JIT编译)
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    由于在多次的调用中产生了JIT编译,导致指令重排后,不再从主内存获取变量的值,导致代码陷入循环中,一直执行。
    总结:一个线程对某个变量进行修改,另一个线程获取不到变量修改后的值,即为可见性问题,导致原因cpu指令重排。

1.4 可见性问题的解决

在这里插入图片描述

2.Java内存模型具体内容

概述:要了解Java内存模型,首先要了解什么是内存模型,之前在CPU缓存和内存屏障中我们了解到缓存一致性问题以及处理器优化的指令重排序问题。为了保证并发编程中可以满足原子性、可见性及有序性。有一个重要的概念,那就是——内存模型。它解决了 CPU 多级缓存、处理器优化、指令重排等导致的内存访问问题,保证了并发场景下的一致性、原子性和有序性。而Java内存模型就是解决由于多线程通过共享内存进行通信时,存在的本地内存数据不一致、编译器会对代码指令重排序、处理器会对代码乱序执行等带来的问题的一种规范。目的是保证并发编程场景中的原子性、可见性和有序性。

2.1 Shared Variables定义

在这里插入图片描述

2.2 线程间操作

在这里插入图片描述

2.3 对同步规则的定义

在这里插入图片描述

2.4 happens-before先行发生原则

在这里插入图片描述

2.6 final在JMM中的处理

在这里插入图片描述

2.7 Word Tearing字节处理

在这里插入图片描述

2.8 double和long的特殊处理

在这里插入图片描述

2.9 Java内存模型回顾

在这里插入图片描述

基于C#的跨平台上位机开发:一次编写,多平台运行 摘要: 本文探讨了如何利用C#进行跨平台上位机开发,以适配Windows、Linux、macOS等多平台需求。通过分析传统单平台开发的局限性(如API差异、硬件接口兼容性),提出基于.NET 5/6/7的解决方案,重点推荐Avalonia(类WPF的跨平台UI框架)和GtkSharp(基于GTK+)实现图形界面。同时,针对硬件通信需求,介绍了System.IO.Ports串口通信和LibUsbDotNet的跨平台支持,并强调多平台调试(VS Code、Docker)的重要性,最终实现一次编码、多端部署的高效 阅读详情

相关推荐

使用Java实现CRC16 MODBUS 格式校验

CRC16校验,测试如下 String str = "a5 98 03 00 00 5f c6 0f 7c 40 78 06 09 46 dc 6e db 00 16 3e 12 5c 98 00 19 98 0e 10 03 06 09 46 dc 6e db 03 0b bf 5f c6 0f 7c 43 bd b9 61 ee 96 76 99"; 校验规则: /** * CRC16_CCITT:多项式x16+x12+x5+1(0x1021),初始值0x0000,低位在前,高位在后,结

weixin_45063710的博客 1315

了解Java可见性的本质

前一段时间重温了伪共享(false sharing)问题,了解到深处有几个问题一直想不明白,加上开发过程中遇到volatile时总觉得理解不够透彻,借着这次脑子里这几个问题,探究下Java可见性的本质到底是什么。

阿里技术 3188

STM32F030F4P6 ADC多通道定时器触发DMA搬运

主函数中等待转换完成的标志位,然后打印出来。ADC回调函数中将数值赋值给变量。配置定时器1s读一次。

qq_24426625的博客 1356

【JavaEE初阶 — 多线程】内存可见性问题 & volatile

【JavaEE初阶 — 多线程】讲解内存可见性问题的产生,引入volatile 关键字,详解JMM模型

OuO-1 的博客 1254

drm 之modes

#define _GNU_SOURCE #include <errno.h> #include <fcntl.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/mman.h> #include <time.h&...

u012794472的专栏 3718

【EtherCAT实践篇一】TwinCAT 3安装、使用

FULL(XAE)安装包:包含了XAR的功能,并能进行多种语言的编程和硬件组态,通常安装在编程电脑上;XAR安装包:包含了ADS的功能,是实时运行环境,对 TwinCAT 模块进行加载、执行、管理、实时运行与调用,通常安装在PLC中;RM安装包:在装了高版本的TwinCAT 3后,发现PLC中的TwinCAT版本较低,就需要安装相应低版本的RM安装包切换版本使用(注:4024无法使用RM安装包切换到低于4022的版本,如4020/4018/4016版本。

JXES智能生态系统 5126

java线程可见性

java线程可见性

大连赵哥的博客 604

MATLAB与ROS联合仿真——订阅ROS消息类功能模块介绍

MATLAB与ROS联合仿真——订阅ROS消息类功能模块介绍 (1)输入参数:无 (2)输出参数:Xr和Yr是小车当前在世界坐标系下的坐标 (3)主要作用:作为ROS与MATLAB的通讯接口,从ROS中订阅小车当前的位置信息,并输出 (4)内部结构: (5)具体实现过程:通过ROS工具箱中的Subscribe模块从ROS中订阅话题/gazebo/link_statesa 通过Bus Selector模块选择ROS总线中的Pose

慕羽★的博客 2699

Java【多线程基础3】导致线程不安全的 4 种原因及解决方式

本篇带你了解Java多线程中线程不安全的原因和解决方案!! 代码示例+解析

yzhcjl_的博客 2247

全志V3S嵌入式驱动开发(uboot移植)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 安装了ubuntu操作系统,有了开发板,下面就可以进行我们的开发工作了。第一步,我们要面临的问题就是uboot移植。一般来说,嵌入式的基础环境就是uboot、linux和rootfs。uboot完成一些基本硬件的初始化,比如cpu频率设置、ddr初始化、加载linux等等。早前,uboot的烧入比较麻烦,需要jtag工具才能完成。现在来说,很多soc支持系统直接从sd卡启动,这对开发

嵌入式-老费,一个分享专业嵌入式知识的blog 2818

面向边缘计算的YOLOv12模型剪枝-蒸馏联合优化实战教程**

这套剪枝-蒸馏联合方案的优势在于其系统性和可靠性。它不是单一的技巧,而是一套完整的工程流程,确保了从研发到部署的无缝衔接。

FJN110的博客 159

揭秘Java内存模型:那些让人头疼的可见性问题

另外,为了确保isDataExpired()方法的正确性,除了使用volatile外,还可以考虑使用synchronized或Lock等同步机制来确保在判断数据过期时,lastUpdateTime的值不会被其他线程修改。可见性问题对程序的影响是巨大的。volatile关键字是Java提供的一种轻量级的同步机制,它可以确保变量在每次读取前都从主内存中刷新,并在修改后立即写入主内存。当一个变量被声明为volatile时,它保证了修改的值会立即被更新到主内存,当有其他线程需要读取时,它会去主内存中读取新值。

guangzhi0633的专栏 1096

使用MATLAB实时处理摄像头图像

本文介绍了如何使用MATLAB进行实时图像处理,包括从摄像头获取图像、对图像进行处理并显示处理结果。我们将演示如何使用MATLAB的图像处理工具箱来实现常见的图像处理任务,如图像增强、边缘检测和物体检测。

XsiJava的博客 921

Java内存模型详解:5大核心规则让你彻底理解线程安全与可见性问题

掌握Java内存模型解析,深入理解线程安全与可见性问题。详解主内存与工作内存交互、happens-before规则、原子性、有序性与可见性保障机制,适用于高并发编程场景。系统梳理5大核心规则,助你写出更稳定的多线程程序,值得收藏。

ByteGlow的博客 364

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

java 8根据某个字段去重_Java学习内存模型和线程安全的可见性问题

上次线程池已经说过了,从今天开始一起了解下JVM内存模型详解。(一)容易误解的部分老铁很容易把JAVA的内存区域、JAVA的内存模型,GC分代回收的老年代和新生代也容易搞混,绕进去绕不出来。学习多线程之前一定要搞明白这些问题,可能在你的内心一直认为多线程就是一个工具,所有的底层都是C++来写的,没办法去看,为什么要有java,java其实就是屏蔽了底层的复杂性。① GC内存区域堆的概念,老年代,新...

weixin_34450486的博客 87

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Java内存模型--Jav语言规范 (线程安全之可见性问题)

多线程中的问题: package com.crane.demo; public class Demo10 { int i = 0; boolean isRunning = true ; public static void main(String[] args) throws InterruptedException { Demo10 demo10 =...

再鹤的博客 488

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

java 8根据某个字段去重_面试经典概念:Java内存模型以及线程安全的可见性问题...

上次线程池已经说过了,从今天开始一起了解下JVM内存模型详解。(一)容易误解的部分老铁很容易把JAVA的内存区域、JAVA的内存模型,GC分代回收的老年代和新生代也容易搞混,绕进去绕不出来。学习多线程之前一定要搞明白这些问题,可能在你的内心一直认为多线程就是一个工具,所有的底层都是C++来写的,没办法去看,为什么要有java,java其实就是屏蔽了底层的复杂性。① GC内存区域堆的概念,老年代,新...

weixin_28362173的博客 94

可见性和volatile -- Java并发

  可见性是Java虚拟机上定义的逻辑上的偏序关系。通常指某些操作的结果对后续的其他操作必须是可见的。详细内容参见《Java Concurrency In Practice》,这部分内容通常被称为Java Memory Model,与操作系统Memory Model概念类似。主要通过一个简单程序说明一下,相当于一个学习总结。下面是程序 参考Doug Lea的JSR133 CookBook  h...

iteye_7251的博客 154

JVM进阶——资深面试官必问的Java内存模型

为了解决处理器与内存之间的速度矛盾,引入了高速缓存。缓存一致性。多路处理器系统中,每个处理器有各自的高速缓存,而他们又共享同一主内存。当多个处理器的运算任务额都涉及同一块主存区域的时候,将可能导致各自的缓存数据不一致。为了解决一致性的问题,需要各个处理器在访问缓存时都遵循一些协议,在读写时要根据协议来进行操作。我们将会多次提到“内存模型”一词,可以理解为在特定的操作协议下,对。不同的物理机器可以拥有不同的内存模型。而。除了增加高速缓存,处理器会对代码进行乱序执行优化。对应JVM中的指令重排序。

2401_85191067的博客 2222

Thread安全一一JAVA内存模型与线程安全问题

 此系列文章是参考《JAVA并发编程从入门到精通》一书写的一些读后笔记,其中也会进行扩展补充,写的不准确的地方还望广大同胞指出,大家一起学习,一起码奴。 初识java内存模型  CPU在计算的时候,并不是一直从内存中读取数据,它读取数据的优先级是:寄存器-》高速缓存-》内存,线程计算的时候,原始数据来自内存,在计算过程中,有些数据可能被频繁读取,这些数据被存储在寄存器和高速缓存中,计算完成后...

weixin_37502658的博客 249

线程安全问题

定义 首先大家需要思考一下何为线程安全性呢??? 《Java并发编程实战》书中给出定义:当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在调用代码中不需要任何额外的同步,这个类都能表现出正确的行为,那么这个类就是线程安全的。 对于线程安全性主要从以下几个方面出发:原子性、有序性、可见性。 原子性: 提供互斥访问,同一时刻只能有一个线程对数据进行操作;例如:atomicXXX类,synchronized关键字的应用。 有序性: 一个线程观察其他线程中的指令执行顺序,由

qq_43842093的博客 421

线程安全之可见性

1、并发中变量的可见性问题 在讲解线程安全的可见性问题前,先来解决几个简单的问题: 问题1: 变量分为哪几类? 全局变量有: 属性(静态的、非静态的) 局部变量有: 本地变量 参数 问题2: 如何在多线程下共享数据? 当然在问题1的答案下,我们知道多线程的数据共享可以使用全局变量(静态变量、共享对象)来解决。 问题3: 一个全局变量在线程1中被改变了,在线程2中能否看到该变量的最新值? 可能大多数人都会给出肯定的答案,既然是全局变量,便是所以线程共享的,线程1改了该变

林中静月下仙的博客 648

Java 内存模型与线程安全(19/30)

Java 内存模型描述了 Java 程序中变量的存储顺序和线程间的可见性,以及不同操作之间的关系。JMM 规定了如何在多核 CPU 上协调多个线程对共享数据的访问。在本模块中,我们学习了 Java 内存模型的工作原理、可见性问题以及如何确保线程安全性。通过使用volatile和原子变量等机制,开发者可以有效地避免竞态条件和数据不一致的问题。在下一模块中,我们将深入探讨Java 的流式编程(Streams),了解如何使用 Java Stream API 以声明式的方式操作集合,编写简洁而高效的数据处理代码。

weidl001的博客 1142

Java并发(1) i++的线程安全问题

1. 问题背景条件 多线程操作同一变量 此处不可能是局部变量,肯定是成员变量或静态变量 PS:为什么不可能是局部变量? 需要多线程访问局部变量,那么多个线程就必须在方法中进行定义,如使用匿名内部类方式定义多个线程。 在使用匿名内部类引用局部变量时,局部变量必须通过final来修饰。这样做的原因是变量的生命周期问题。 final修饰的变量,不管是int还是Integer,都不能进行自加操作。 2.

清欢 1万+

“深入浅出”系列之C++:C++11内存模型

在多线程编程的复杂领域中,C++11 内存模型犹如一座灯塔,为开发者指引着正确的方向。它的重要性不言而喻,是编写高效、正确的多线程 C++ 程序的基石。在 C++11 标准发布之前,C++ 语言对于多线程编程的支持相对薄弱,开发者往往需要借助第三方库或平台特定的 API 来实现多线程功能。这不仅增加了代码的复杂性和维护成本,还难以保证程序在不同平台上的一致性和可移植性。C++11 的出现,为多线程编程带来了重大变革。它引入了一系列新的特性和工具,其中内存模型的改进尤为关键。

weixin_65589140的博客 950

java 内存模型

浅谈java内存模型 不同的平台,内存模型是不一样的,但是jvm的内存模型规范是统一的。其实java的多线程并发问题最终都会反映在java的内存模型上,所谓线程安全无非是要控制多个线程对某个资源的有序访问或修改。总结java的内存模型,要解决两个主要的问题:可见性和有序性。 我们都知道计算机有高速缓存的存在,处理器并不是每次处理数据都是取内存的。JVM定义了自己的内存模型,屏蔽了底层平台内...

jipengyun的专栏 104
上一篇: 线程池应用及实现原理剖析
下一篇: 线程安全之原子操作
海尔兵
博客等级 码龄7年 12粉丝 22原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值