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

并发编程之三大特性及JMM内存模型

目录

原子性

如何保证原子性

可见性

如何保证可见性

有序性

如何保证有序性

Java内存模型(JMM内存模型)

Java内存模型的一些关键概念:

主内存与工作内存交互协议

Java内存模型通过以下手段来确保多线程程序的正确性:

锁机制

volatile

volatile禁止指令重排序

 Happens-Before


并发三大特性

原子性、可见性、有序性

原子性

        原子性是指一个操作是不可中断的。一个原子操作是一个不可分割的整体,要么全部执行成功,要么全部不执行。在多线程环境下,当多个线程访问共享变量时,如果其中一个线程在执行某个操作,其他线程不能同时执行该操作。

public class AtomicTest {private static volatile int counter = 0;public static void main(String[] args) {for (int i = 0; i < 10; i++) {Thread thread = new Thread(() -> {for (int j = 0; j < 10000; j++) {//synchronized (AtomicTest.class) {counter++;// }}});thread.start();}try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(counter);}
}

        正常执行后counter变量的值远远大于预期10000,加synchronized后counter变量为10000

如何保证原子性

      1. 通过synchronized关键字保证原子性

      2. 通过 Lock锁保证原子性

      3. 通过 CAS保证原子性


可见性

       可见性是指当一个线程修改了共享变量的值时,其他线程能够立即看到这个修改。在多线程环境下,由于线程之间的缓存机制,一个线程对共享变量的修改可能不会立即被其他线程看到。

 

public class VisibilityExample {private static boolean stop = false;public static void main(String[] args) {// 线程1:修改共享变量Thread thread1 = new Thread(() -> {while (!stop) {// do something}System.out.println("Thread 1 finished");});// 线程2:修改共享变量Thread thread2 = new Thread(() -> {stop = true;System.out.println("Thread 2 set stop to true");});// 启动线程1thread1.start();// 稍等片刻try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}// 启动线程2thread2.start();}
}

       在以上代码中,两个线程分别运行,并且共享一个stop变量。线程1在一个循环中检查stop变量是否为false,而线程2在启动后将stop变量设置为true。然而,由于没有同步机制,线程1可能不会立即看到线程2对stop变量的修改,导致线程1一直在循环中无法退出。

private static volatile boolean stop = false;

通过给stop变量增加volatile修饰,即可保证可见性。

如何保证可见性

       通过volatile 关键字保证可见性
       通过内存屏障保证可见性
       通过synchronized 关键字保证可见性
       通过Lock锁保证可见性


有序性

       有序性是指程序执行的顺序按照代码的先后顺序执行。在多线程环境下,由于指令重排序等优化,有时候线程执行的顺序可能与代码的顺序不一致。

public class ReOrderTest {private static  int x = 0, y = 0;private  static  int a = 0, b = 0;public static void main(String[] args) throws InterruptedException {int i=0;while (true) {i++;x = 0;y = 0;a = 0;b = 0;Thread thread1 = new Thread(new Runnable() {@Overridepublic void run() {//用于调整两个线程的执行顺序shortWait(20000);a = 1; x = b; }});Thread thread2 = new Thread(new Runnable() {@Overridepublic void run() {b = 1;y = a;}});thread1.start();thread2.start();thread1.join();thread2.join();System.out.println("第" + i + "次(" + x + "," + y + ")");if (x==0&&y==0){break;}}}public static void shortWait(long interval){long start = System.nanoTime();long end;do{end = System.nanoTime();}while(start + interval >= end);}
}

执行结果:x,y出现了0,0的结果,程序终止。出现这种结果有可能是重排序导致的。

如何保证有序性

       通过volatile 关键字保证有序性
       通过内存屏障保证有序性 
       通过synchronized关键字保证有序性
       通过Lock锁保证有序性


Java内存模型(JMM内存模型)

       Java内存模型(Java Memory Model,JMM)是Java程序中多线程并发访问共享变量时,对内存操作行为的一种规范。它定义了在多线程环境中,线程如何与主内存和工作内存交互,以确保并发程序的正确性。

              

Java内存模型的一些关键概念:

1. 主内存(Main Memory): 主内存是所有线程共享的内存区域,包含所有的共享变量。所有的线程都可以访问主内存。
2. 工作内存(Working Memory): 每个线程有自己的工作内存,存储了该线程使用到的变量的副本。线程对变量的所有操作都在工作内存中进行,不直接读写主内存。
3. 共享变量: 多个线程之间可以共享的变量,例如类的静态变量或实例变量。
4. 原子性(Atomicity): 单个的读/写操作是原子的,即要么完成,要么不开始。
5. 可见性(Visibility): 当一个线程修改了共享变量的值,其他线程应该能够立即看到这个变化。
6. 有序性(Ordering): 程序执行的顺序与代码中的顺序一致。

主内存与工作内存交互协议

从工 作内存同步到主内存之间的实现细节,Java内存模型定义了以下八种原子操作来完成:
lock(锁定):作用于主内存的变量,把一个变量标识为一条线程独占状态。
unlock(解锁):作用于主内存变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁 定。
read(读取):作用于主内存变量,把一个变量值从主内存传输到线程的工作内存中,以便随后的load动作使用
load(载入):作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中。
use(使用):作用于工作内存的变量,把工作内存中的一个变量值传递给执行引擎,每当虚拟机遇到一个需要 使用变量的值的字节码指令时将会执行这个操作。
assign(赋值):作用于工作内存的变量,它把一个从执行引擎接收到的值赋值给工作内存的变量,每当虚拟机 遇到一个给变量赋值的字节码指令时执行这个操作。
store(存储):作用于工作内存的变量,把工作内存中的一个变量的值传送到主内存中,以便随后的write的操 作。
write(写入):作用于主内存的变量,它把store操作从工作内存中得到的变量的值放入主内存的变量中。

Java内存模型通过以下手段来确保多线程程序的正确性:

1. 锁机制: 使用synchronized关键字或显式锁来保护共享数据,确保在同一时刻只有一个线程可以访问临界区。
2. volatile关键字: 用于修饰共享变量,保证可见性。对一个volatile变量的写操作将立即刷新到主内存,而读操作将从主内存中加载最新的值。
3. final关键字: 被final修饰的字段在构造函数结束之前就已经对其他线程可见。
4. Happens-Before关系: JMM定义了Happens-Before的规则,确保在某个操作之前的操作对其可见。

锁机制

1. 当线程获取锁时,JMM会把该线程对应的本地内存置为无效。
2. 当线程释放锁时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存中。

       synchronized关键字的作用是确保多个线程访问共享资源时的互斥性和可见性。在获取锁之前,线程 会将共享变量的最新值从主内存中读取到线程本地的缓存中,释放锁时会将修改后的共享变量的值刷 新到主内存中,以保证可见性。

volatile

1. 当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量值刷新到主内存。
2. 当读一个volatile变量时,JMM会把该线程对应的本地内存置为无效,线程接下来将从主内存中读取共享变量。

volatile禁止指令重排序

 Happens-Before

       Happens-Before是Java内存模型(Java Memory Model,JMM)中一个重要的概念,用于规定多线程程序中操作之间的执行顺序和可见性关系。这个概念确保了在程序中对共享变量的操作是按照一定顺序执行的,以避免出现不确定的结果和数据竞争问题。

       如果操作A在操作B之前发生在之前(happens-before),那么操作A对于操作B来说,必定是可见的,而且操作A的效果将被操作B看到。  

Happens-Before部分关系规则:

1. 程序顺序规则(Program Order Rule): 在一个线程中,操作按照程序代码的先后顺序执行。
2. 锁定规则(Lock Rule): 释放锁的操作Happens-Before于后续对同一锁的加锁操作。
3. volatile变量规则(Volatile Variable Rule): 对volatile变量的写操作Happens-Before于后续对这个变量的读操作。
4. 传递性(Transitivity): 如果操作A Happens-Before于操作B,且操作B Happens-Before于操作C,那么操作A Happens-Before于操作C。
5. 线程启动规则(Thread Start Rule): 线程的启动操作Happens-Before于该线程的任何操作。
6. 线程终止规则(Thread Termination Rule): 线程的所有操作Happens-Before于其他线程检测到该线程已经终止。

相关文章:

并发编程之三大特性及JMM内存模型

目录 原子性 如何保证原子性 可见性 如何保证可见性 有序性 如何保证有序性 Java内存模型(JMM内存模型) Java内存模型的一些关键概念&#xff1a; 主内存与工作内存交互协议 Java内存模型通过以下手段来确保多线程程序的正确性&#xff1a; 锁机制 volatile volat…...

centos系统设置runlevel为5

在 CentOS 系统中&#xff0c;可以使用以下步骤将运行级别&#xff08;runlevel&#xff09;设置为 5&#xff1a; 1. 打开终端或 SSH 连接到 CentOS 服务器。 2. 以 root 用户身份登录。 3. 运行以下命令来编辑 /etc/inittab 文件&#xff1a; shell sudo vi /etc/inittab…...

关于群晖ARPL界面能出现ip但是使用Synology Assistant搜索不到ip问题 及解决方法

文章引用ing304 频道文章&#xff1a;https://qun.qq.com/qqweb/qunpro/share?_wv3&_wwv128&appChannelshare&inviteCode20jx8dPsU2z&contentID1m4NKs&businessType2&from181174&shareSource5&bizka 前言 当进入该界面后 提示IP无法访问&a…...

mysql Linux系统云服务器配置远程访问

mysql Linux系统云服务器配置远程访问 1.安装mysql 服务器 2.配置远程登录用户权限 3.进行远程登录&#xff0c;并访问数据库 1.安装mysql 服务器 首先先安装一下云服务器 sudo apt-get install mysql-server安装好之后&#xff0c;我们直接以root用户登录&#xff1a; …...

使用WAF防御网络上的隐蔽威胁之SQL注入攻击

SQL注入攻击是一种普遍存在且危害巨大的网络安全威胁&#xff0c;它允许攻击者通过执行恶意的SQL语句来操纵或破坏数据库。 这种攻击不仅能够读取敏感数据&#xff0c;还可能用于添加、修改或删除数据库中的记录。因此&#xff0c;了解SQL注入攻击的机制及其防御策略对于保护网…...

【书生·浦语】大模型实战营——第五次课程作业

基础作业——使用LMDeploy 以本地对话、网页Gradio、API服务中的一种方式部署InternLM-Chat-7B模型&#xff0c;生成300字的小故事 环境准备 除了安装所需依赖之后&#xff0c;重要的是进行模型转化&#xff08;转换成TurboMind格式&#xff09;&#xff0c;这里需要注意转化命…...

Unity | 渡鸦避难所-7 | 攻击碰撞检测

1 前言 英雄的宝剑并非只是装饰物&#xff0c;利剑出鞘时可以对怪物造成伤害。同样&#xff0c;怪物挥出铁拳时也会对英雄造成伤害。当然&#xff0c;都有同样的前提&#xff1a;在武器碰到对方的情况下&#xff0c;才会造成伤害。利用物理引擎&#xff0c;可以轻松的实现碰撞…...

Linux Mii management/mdio子系统分析之一 总体概述

Linux Mii management/mdio子系统分析之一 总体概述 &#xff08;转载&#xff09;原文链接&#xff1a;https://blog.csdn.net/u014044624/article/details/123303099 从本章开始&#xff0c;我们介绍linux的mii management对应的mdio子模块&#xff0c;该模块主要用于管理phy…...

C语言:自定义类型——联合和枚举

一、联合体 1.1 联合体类型的声明 像结构体⼀样&#xff0c;联合体也是由⼀个或者多个成员构成&#xff0c;这些成员可以是不同的类型。 声明方式如下图&#xff1a; 那联合体和结构体究竟有什么区别呢&#xff1f;&#xff1f; 下面将重点讲解联合体的特点&#xff01;&am…...

uniapp微信小程序投票系统实战 (SpringBoot2+vue3.2+element plus ) -用户投票实现

锋哥原创的uniapp微信小程序投票系统实战&#xff1a; uniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )_哔哩哔哩_bilibiliuniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )共计21条视频…...

如何实现一个两栏布局,右侧自适应?三栏布局中间自适应?

要实现一个两栏布局&#xff0c;右侧自适应的效果&#xff0c;可以使用 CSS 的 Flexbox 或 Grid 布局来实现。以下是使用 Flexbox 实现的示例&#xff1a; HTML 结构&#xff1a; htmlCopy Code<div class"container"><div class"left-column"&…...

004 Golang-channel-practice 左右括号匹配

第四题 左右括号打印 一个协程负责打印“&#xff08;”&#xff0c;一个协程负责打印“&#xff09;”&#xff0c;左右括号的数量要匹配。在这道题目里&#xff0c;我在main函数里进行了一个死循环。会产生一个随机数&#xff0c;随机数就是接下来要打印的左括号的数量。 例…...

MS2351M/MS2351D:RF 检测器/控制器

产品简述 MS2351M/MS2351D 是一款对数放大器芯片&#xff0c;主要用于接收 信号强度指示 (RSSI) 与 控 制 功 率 放 大 器 &#xff0c; 工 作 频 率 范 围 是 0.05GHz  4.0GHz &#xff0c;动态范围随信号频率不同可达 35dB 到 45dB 。 MS2351M/MS2351D 是电压响…...

vue中使用js-doc

安装依赖 安装vue-template-compiler npm install ​vue-template-compiler​ 安装minami npm install minami 安装js-doc npm install js-doc 根目录下创建 .jsdoc.conf.json 内容&#xff1a; {"tags": {"allowUnknownTags": true,// 指定所用词…...

Hive知识点

基本概念&#xff1a; 由Facebook开源&#xff0c;构建在Hadoop之上的数据仓库&#xff0c;数据计算是mapreduce&#xff0c;数据存储是HDFS 目的是构建面向分析的集成的数据环境&#xff0c;为企业提供决策支持 &#xff08;面向分析的存储系统&#xff09; 主要特征&…...

android自启动

Android 开机自动启动一个Service 附源码_watchdogservice-CSDN博客 执行 adb push 本地地址 目标地址 时遇到错误&#xff1a; adb: error: failed to copy app-release.apk to /system/app/app-release.apk: remote couldnt create file: Read-only file system 解决方案…...

cookie、Web Storage

前端知识汇编 1. cookie1.1 cookie的限制1.2 cookie的构成1.3 JavaScript中的cookie1.4 子cookie1.5 使用cookie的注意事项 2. Web Storage2.1 Storage类型2.2 sessionStorage对象2.3 localStorage对象2.4 存储事件2.5 限制 1. cookie cookie是客户端与服务器端进行会话时使用…...

【rk3568】01-环境搭建

文章目录 1.开发板介绍1.1相关资源&#xff1a;1.2接口布局1.3屏幕1.4核心板引脚可复用资源 2.环境搭建2.1安装依赖包2.2git配置2.3安装sdk2.4sdk介绍2.5sdk编译 3.镜像介绍 1.开发板介绍 开发板&#xff1a;atk-rk3568开发板 eMMC&#xff1a;64G LPDDR4&#xff1a;4G 显示屏…...

编程笔记 html5cssjs 036 CSS概述

编程笔记 html5&css&js 036 CSS概述 一、什么是 CSS?二、样式非常重要三、CSS 语法四、CSS 注释五、示例 CSS (Cascading Style Sheets&#xff0c;层叠样式表&#xff09;&#xff0c;是一种用来为结构化文档&#xff08;如 HTML 文档或 XML 应用&#xff09;添加样式…...

Vue入门七(Vuex的使用|Vue-router|LocalStorage与SessionStorage和cookie的使用)

文章目录 一、Vuex1&#xff09;理解vuex2&#xff09;优点3&#xff09;何时使用&#xff1f;4&#xff09;使用步骤① 安装vuex② 注册vuex③ 引用vuex④ 创建仓库Store五个模块介绍 5&#xff09;基本使用 二、Vue-router三、LocalStorage与SessionStorage、cookie的使用 一…...

OpenClaw+Qwen3.5-9B低成本方案:自建接口替代OpenAI API

OpenClawQwen3.5-9B低成本方案&#xff1a;自建接口替代OpenAI API 1. 为什么选择Qwen3.5-9B作为OpenClaw的本地大脑 去年冬天&#xff0c;当我第一次尝试用OpenClaw自动化处理周报时&#xff0c;被OpenAI API的账单吓了一跳——简单的文件整理和摘要生成&#xff0c;一周竟消…...

学习Spring Ai的摸索实践

摸索AI&#xff08;一&#xff09;安装Ollama和本地大模型部署https://www.chendd.cn/blog/article/2012500757664628737.html摸索AI&#xff08;二&#xff09;Spring AI实现的Hello Worldhttps://www.chendd.cn/blog/article/2013071822723874817.html 摸索AI&#xff08;三…...

微信小程序框架详解

小程序包含一个描述整体程序的app实例和多个描述页面的page。其中app由三个文件构成:公共配置app.json、公共样式app.wxss、主体逻辑app.js。每个page最多由四个文件构成:页面配置page.json、页面结构page.wxml、页面样式page.wxss、页面主体逻辑page.js。 微信小程序的主体部…...

AI 写作 + 去 AI 味:自媒体人高效涨粉密码

AI 写作 去 AI 味&#xff0c;自媒体人高效涨粉的新组合拳副标题&#xff0c;内容洪流时代&#xff0c;创作者如何同时兼顾效率、风格与平台合规&#xff1f;凌晨两点&#xff0c;北京东四环的一间合租公寓里&#xff0c;一位运营着 3 个帐号的图文博主&#xff0c;一边看着后…...

Leader让我带5个外包,出了问题算我的,绩效好了算团队的,每天当保姆还不如自己写,管理岗这个坑谁爱跳谁跳

看到一哥们吐槽&#xff0c;说leader让他带5个外包&#xff0c;出了问题算他的&#xff0c;绩效好了算团队的&#xff0c;每天当保姆还不如自己写代码。看完我直接笑出声了——不是觉得好笑&#xff0c;是太真实了&#xff0c;笑的是自己也经历过。说实话&#xff0c;这种事在互…...

Mermaid在线编辑器终极指南:免费实时图表创作工具完全解析

Mermaid在线编辑器终极指南&#xff1a;免费实时图表创作工具完全解析 【免费下载链接】mermaid-live-editor Edit, preview and share mermaid charts/diagrams. New implementation of the live editor. 项目地址: https://gitcode.com/GitHub_Trending/me/mermaid-live-ed…...

长尾关键词SEO优化费用如何计算_企业自营SEO关键词优化成本是多少

长尾关键词SEO优化费用如何计算_企业自营SEO关键词优化成本是多少 在当今数字化时代&#xff0c;SEO&#xff08;搜索引擎优化&#xff09;已经成为企业提升网站流量、增加品牌曝光度的重要手段。其中&#xff0c;长尾关键词SEO优化因其较低的竞争度和高转化率&#xff0c;备受…...

LAV Filters专业配置进阶指南:深度解析开源解码器架构与性能优化

LAV Filters专业配置进阶指南&#xff1a;深度解析开源解码器架构与性能优化 【免费下载链接】LAVFilters LAV Filters - Open-Source DirectShow Media Splitter and Decoders 项目地址: https://gitcode.com/gh_mirrors/la/LAVFilters LAV Filters是一套基于FFmpeg的高…...

颠覆性视频转文字体验:零基础掌握bili2text全流程攻略

颠覆性视频转文字体验&#xff1a;零基础掌握bili2text全流程攻略 【免费下载链接】bili2text Bilibili视频转文字&#xff0c;一步到位&#xff0c;输入链接即可使用 项目地址: https://gitcode.com/gh_mirrors/bi/bili2text 还在为从B站视频中提取文字内容而烦恼&…...

Amazon Q 从入门到实战,AWS 专属 AI 助手超全指南

目录 一、Amazon Q 到底是什么 二、Amazon Q 有两个版本 1、Amazon Q Developer&#xff08;给开发者/运维&#xff09; 2、Amazon Q Bussiness&#xff08;给企业/业务人员&#xff09; 三、Amazon Q能解决什么实际问题 四、Amazon Q 和 Chat GPT 同类助手的有什么区别 …...