当前位置: 首页 > news >正文

线程安全-3 JMM

一.谈一下JMM

1.JMM,JavaMemoryModel,Java内存模型。定义了多线程对共享内存读写操作的行为规范,通过规范多线程对共享内存的读写操作,以保证指令执行和结果的正确性。

2.JMM把内存分为两块

(1)主内存:是线程间共享的内存区域,可以被所有线程访问,存储了共享变量的原始副本。

(2)工作内存:是线程的私有区域,每个线程都有一个自己的工作内存,是线程的工作区域,不同线程的工作内存相互独立、相互隔离。

        a.线程的工作内存相互隔离,每个线程都只能访问属于自己的工作内存。

        b.线程不直接操作主内存的数据,而是将主内存的数据拷贝一份到自己的工作内存中,进行操作,操作完再将数据更新到主内存。

        c.线程在自己的工作内存对主内存变量的副本进行修改后,通过CAS操作将其更新到主内存的变量中,其他线程再将主内存变量的最新值更新到自己的副本变量中。不同线程是通过主内存进行交互的。

3.JMM的8个原子操作

(1)read:读取,读取主内存的变量值到工作内存中

(2)load:载入,将从主内存读到的变量值放到工作内存的副本变量中

(3)store:存储,将工作内存的变量值送到主内存中

(4)write:写入,将工作内存送来的变量值写入到主内存的变量中

(5)use:使用,将工作内存的变量值传递给执行引擎,以供其他指令需要

(6)assign:赋值,将从执行引擎获取到的值赋值给工作内存的变量

(7)lock:加锁,将主内存的变量标记为线程独占状态

(8)unlock:解锁,将主内存的变量的加锁状态解除

二.并发编程的三大特征是什么? / 导致并发程序出现问题的根本原因是什么?

1.原子性:一个操作要么全部完成,要么全部都不完成,不会因为上下文切换而导致结果出错。

2.可见性:虽然每个线程只能操作自己工作内存的数据,自己的工作内存对其他线程不可见;但是当一个线程对主内存的共享变量进行更新后,其他线程要能立即知道并更新为最新值。

3.有序性:为了提高运行效率,编译器会对代码进行重排序,cpu也会对指令进行重排序;这种重排序不会影响单线程的执行结果,但会影响多线程并发执行的结果。因此并发编程要能保证重排序之后的有序性,执行结果不会因重排序而出错。

三.JMM如何保证并发编程三大特征? / Java程序中如何保证多线程的执行安全?

1.原子性:synchronized、JUC中的Lock

2.可见性:volatile、synchronized、JUC中的Lock

3.有序性:volatile、synchronized

四.说一下volatile关键字

volatile关键字用于修饰共享变量(类的成员变量和静态成员变量),具有两种作用

1.保证并发编程的可见性

(1)问题1:JVM提供了一个即时编译器JIT,会对代码进行优化。例如while(!stop),stop默认为false。如果当前代码的执行逻辑中没有对stop进行修改,则会将代码优化为while(true),这在单线程下是可行的;但是在多线程中,若有其他线程对stop进行更改,由于代码优化,会导致执行当前代码的线程无法收到其他线程对stop的更改通知,失去了并发编程的可见性。

(2)问题2:若线程在更新主内存的共享变量后,其他线程未及时同步最新值,则其他线程在工作内存中的变量副本就相当于失效了,这也失去了并发编程的可见性。

(3)解决:使用volatile修饰共享变量

        a.使用volatile修饰的变量,可以防止JIT对其进行优化

        b.使用volatile修饰的变量,会对其读写操作加上属于硬件层面的内存屏障

                对volatile变量执行读操作前,会插入即读屏障,强行使当前工作内存的变量失效,重新去主内存获取变量值

                对volatile变量进行写操作后,会插入即写屏障,强行将工作内存的变量最新值更新到主内存中

2.保证并发编程的有序性

(1)问题:编译器为了提高效率会对代码进行重排序,影响了高并发下的执行结果

(2)解决:用volatile修饰的变量,会对其读写操作加上属于JMM层面的内存屏障,保证重排序后的有序性。

        LoadBarrier;

        volatile读操作; //重排序时,其上所有读操作不能越过屏障排到下面,其下所有写操作不能越过屏障跑到上面

        StoreBarrier;

        ...

        StoreBarrier;

        volatile写操作; //重排序时,其上所有写操作不能越过屏障排到下面,其下所有读操作不能越过屏障跑到上面

        LoadBarrier;

                

相关文章:

线程安全-3 JMM

一.谈一下JMM 1.JMM,JavaMemoryModel,Java内存模型。定义了多线程对共享内存读写操作的行为规范,通过规范多线程对共享内存的读写操作,以保证指令执行和结果的正确性。 2.JMM把内存分为两块 (1)主内存&a…...

4 CSS的 变换、过渡与动画

CSS3引入了变换、过渡和动画特性,使得网页可以呈现出丰富的视觉效果和交互体验。通过这些新特性,开发者可以创建复杂的动画效果,而不需要使用JavaScript。 4.1 变换(Transforms) 变换允许开发者对元素进行旋转、缩放…...

前端基础入门三大核心之JS篇:掌握数字魔法 ——「累加器与累乘器」的奥秘籍【含样例代码】

前端基础入门三大核心之JS篇:掌握数字魔法 ——「累加器与累乘器」的奥秘籍 🧙‍♂️ 基础概念:数字的魔杖与炼金术累加器(Accumulator)累乘器(Multiplier) 📚 实战演练:…...

git clone 出现的问题

问题: core源码ref新API % git clone https://github.com/xxxx.git Cloning into core... remote: Enumerating objects: 58033, done. remote: Counting objects: 100% (1393/1393), done. remote: Compressing objects: 100% (750/750), done. error: 432 bytes of body are …...

Vue2和Vue3生命周期的对比

Vue2和Vue3生命周期的对比 Vue2 和 Vue3 生命周期对照表Vue2 和 Vue3 生命周期图示 Vue2 和 Vue3 生命周期对照表 触发时机Vue2.xVue3.x组件创建时运行beforeCreate setup createdsetup 挂载在DOM时运行beforeMountonBeforeMountmountedonMounted响应数据修改时运行beforeUpdat…...

全面解析Java.lang.ClassCastException异常

全面解析Java.lang.ClassCastException异常 全面解析Java.lang.ClassCastException异常:解决方案与最佳实践 🚀📚摘要引言1. 什么是Java.lang.ClassCastException?代码示例 2. 报错原因2.1 类型不兼容2.2 泛型类型擦除2.3 接口和实…...

美团Java社招面试题真题,最新面试题

如何处理Java中的内存泄露? 1、识别泄露: 使用内存分析工具(如Eclipse Memory Analyzer Tool、VisualVM)来识别内存泄露的源头。 2、代码审查: 定期进行代码审查,关注静态集合类属性和监听器注册等常见内…...

二十八、openlayers官网示例Data Tiles解析——自定义绘制DataTile源数据

官网demo地址: https://openlayers.org/en/latest/examples/data-tiles.html 这篇示例讲解的是自定义加载DataTile源格式的数据。 先来看一下什么是DataTile,这个源是一个数组,与我们之前XYZ切片源有所不同。DataTile主要适用于需要动态生成…...

分布式事务解决方案(最终一致性【TCC解决方案】)

最终一致性分布式事务概述 强一致性分布式事务解决方案要求参与事务的各个节点的数据时刻保持一致,查询任意节点的数据都能得到最新的数据结果,这就导致在分布式场景,尤其是高并发场景下,系统的性能受到了影响。而最终一致性分布式…...

App Inventor 2 Encrypt.Security 安全性扩展:MD5哈希,SHA/AES/RSA/BASE64

这是关于App Inventor和Thunkable安全性的扩展,它提供MD5哈希,SHA1和SHA256哈希,AES加密/解密,RSA加密/解密,BASE64编码/解码方法。 权限 此扩展程序不需要任何权限。 事件 OnErrorOccured 抛出任何异常时将触发此事件…...

深入了解Linux中的环境变量

在Linux系统中,环境变量(Environment Variables)是用于配置操作系统和应用程序运行环境的一种机制。它们储存在键值对中,可以控制程序的行为、路径查找和系统配置。本文将深入探讨环境变量的基本概念、常见类型、设置和管理方法&a…...

雷军-2022.8小米创业思考-8-和用户交朋友,非粉丝经济;性价比是最大的诚意;新媒体,直播离用户更近;用真诚打动朋友,脸皮厚点!

第八章 和用户交朋友 2005年,为了进一步推动金山的互联网转型,让金山的同事更好地理解互联网的精髓,我推动了一场向谷歌学习的运动,其中一个小要求就是要能背诵“谷歌十诫”。 十诫的第一条就令人印象深刻:以用户为中…...

【Vue2.x】props技术详解

1.什么是prop? 定义:组件标签上注册的一些自定义属性作用:向子组件传递数据特点 可以传递任意数量的prop可以传递任意类型的prop 2.prop校验 为了避免乱传数据,需要进行校验 完整写法 将之前props数组的写法,改为对象…...

C语言例题46、根据公式π/4=1-1/3+1/5-1/7+1/9-1/11+…,计算π的近似值,当最后一项的绝对值小于0.000001为止

#include <stdio.h> #include <math.h>int main() {int fm 1;//分母double sign 1;//正负号double fzs 1;//分子式double sum 0;while (fabs(fzs) > 0.000001) {sum fzs;sign * -1; //变换正负号fm 2; //分母3、5、7、9...增长fzs sign / fm;//分子式…...

fpga系列 HDL: 05 阻塞赋值(=)与非阻塞赋值(<=)

在Verilog硬件描述语言&#xff08;HDL&#xff09;中&#xff0c;信号的赋值方式主要分为两种&#xff1a;连续赋值和过程赋值。每种赋值方式有其独特的用途和语法&#xff0c;并适用于不同类型的电路描述。 1. 连续赋值&#xff08;Continuous Assignment,assign 和&#xf…...

大白话DC3算法

DC3算法是什么 DC3算法&#xff08;也称为Skew算法&#xff09;是一种高效的构建后缀数组的算法&#xff0c;全称为Difference Cover Modulo 3算法。 该算法于2002年被提出&#xff0c;论文参考&#xff1a; https://www.cs.cmu.edu/~guyb/paralg/papers/KarkkainenSanders0…...

力扣HOT100 - 75. 颜色分类

解题思路&#xff1a; 单指针&#xff0c;对数组进行两次遍历。 class Solution {public void sortColors(int[] nums) {int p 0;int n nums.length;for (int i 0; i < n; i) {if (nums[i] 0) {int tmp nums[i];nums[i] nums[p];nums[p] tmp;p;}}for (int i p; i …...

Vue.js - 计算属性与侦听器 【0基础向 Vue 基础学习】

文章目录 计算属性 computedcomputed 的使用方法computed 与 method 的区别计算属性完整写法 watch 侦听器&#xff08;监视器&#xff09;简单写法 → 简单类型数据&#xff0c;直接监视完整写法 → 添加额外配置项 计算属性 computed computed 的使用方法 **概念&#xff1…...

技术速递|使用 C# 集合表达式重构代码

作者&#xff1a;David Pine 排版&#xff1a;Alan Wang 本文是系列文章的第二篇&#xff0c;该系列文章涵盖了探索 C# 12功能的各种重构场景。在这篇文章中&#xff0c;我们将了解如何使用集合表达式重构代码&#xff0c;我们将学习集合初始化器、各种表达式用法、支持的集合目…...

我的世界开服保姆级教程

前言 Minecraft开服教程 如果你要和朋友联机时&#xff0c;可以选择的方法有这样几种&#xff1a; 局域网联机&#xff1a;优点&#xff1a;简单方便&#xff0c;在MC客户端里自带。缺点&#xff1a;必须在同一局域网内。 有些工具会带有联机功能&#xff1a;优点&#xff1a;一…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

OpenLayers 分屏对比(地图联动)

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能&#xff0c;和卷帘图层不一样的是&#xff0c;分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...

Docker 本地安装 mysql 数据库

Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker &#xff1b;并安装。 基础操作不再赘述。 打开 macOS 终端&#xff0c;开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...

算法:模拟

1.替换所有的问号 1576. 替换所有的问号 - 力扣&#xff08;LeetCode&#xff09; ​遍历字符串​&#xff1a;通过外层循环逐一检查每个字符。​遇到 ? 时处理​&#xff1a; 内层循环遍历小写字母&#xff08;a 到 z&#xff09;。对每个字母检查是否满足&#xff1a; ​与…...

【网络安全】开源系统getshell漏洞挖掘

审计过程&#xff1a; 在入口文件admin/index.php中&#xff1a; 用户可以通过m,c,a等参数控制加载的文件和方法&#xff0c;在app/system/entrance.php中存在重点代码&#xff1a; 当M_TYPE system并且M_MODULE include时&#xff0c;会设置常量PATH_OWN_FILE为PATH_APP.M_T…...

GO协程(Goroutine)问题总结

在使用Go语言来编写代码时&#xff0c;遇到的一些问题总结一下 [参考文档]&#xff1a;https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现&#xff1a; 今天在看到这个教程的时候&#xff0c;在自己的电…...