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

并发——同步访问共享的可变数据

关键字 synchronized 可以保证在同一时刻,只有一个线程可以执行某一个方法,或者某一段代码块。许多程序员把同步的概念仅仅理解为一种互斥的方式。即,当一个对象被一个线程修改的时候,可以阻止另一个线程观察到内部不一致的状态。

这种观点是正确的,但是它并没有说明同步的全部意义。如果没有同步,一个线程的变化就不能被其他线程看到。同步不仅可以阻止一个线程看到对象处于不一致的状态之中,它还可以保证进入同步方法或代码块的每个线程,都看到由一个同步锁保护的之前所有的修改效果。

你可能听说过,为了提高性能,在读或者写原子数据的时候,应该避免使用同步。这个建议是非常危险而错误的。虽然语言规范保证了线程在读取原子数据的时候,不会看到任意的数值,但是它并不保证一个线程写入的值对于另一个线程将是可见的。为了在线程间进行可靠的通信,也为了互斥访问,同步是必要的。这归因于 java 语言规范中的内存模型,它规定了一个线程所做的变化何时以及如何变成对其他线程可见。

如果对共享的可变数据的访问不能同步,其后果将非常可怕,即使这个变量是原子可读写的。

测试以下代码

public class StopThread {private static boolean  stop;public static void main(String[] args) throws InterruptedException {System.out.println(LocalDateTime.now());Thread t = new Thread(()->{int i = 0;while(!stop){i++;}System.out.println(LocalDateTime.now());});t.start();Thread.sleep(1000);stop = true;}
} 

看上去这段代码的意思就是1s 之后停止,但实际上,它根本不会停止;后台线程永远在循环

问题在于,没有同步,就不能保证后台线程什么时候会发现主线程修改了 stop 的值

想要修复的这个问题,可以加上同步操作

public class StopThread {private static boolean  stop;private static synchronized  void setStop(){stop = true;}private static synchronized boolean getStop(){return stop;}public static void main(String[] args) throws InterruptedException {System.out.println(LocalDateTime.now());Thread t = new Thread(()->{int i = 0;while(!getStop()){i++;}System.out.println(LocalDateTime.now());});t.start();Thread.sleep(1000);setStop();}
} 

注意,在上面的修改中,写和读方法都添加了同步关键字。如果只有一个则可能无效,读和写是两个动作,都需要被同步,才能真正完成同步。

synchronized 关键字由java 自动帮我们处理为锁,实际上,针对上面的要求,我们可以用一个更简单高效的关键字来处理:volatile

也就是在stop 前加上 volatile 修饰,就可以了,不需要再用 同步处理读和写。volatile 不提供锁和互斥操作,它只保证内存可见性,这里我们需要的也就是内存可见性——任何线程所修改之后,立刻被其他线程所见。

所以,要正确区分 synchronized 和 volatile 。synchronized 提供互斥操作,也就是任意时刻,所修饰的代码块或方法只能有一个线程在执行。而volatile 只能保证可见,没有互斥性。

以下代码可以做个试验

private static volatile int count = 0;
public static void main(String[] args) throws InterruptedException {for(int x =0;x<10;x++){new Thread(() ->{for(int i =0;i<1000;i++){count ++;}}).start();}Thread.sleep(2000); // 保证多线程已经结束System.out.println(count);
} 

多次执行之后,你会发现,count 不一定是 10000,大概率是9000多。

因为 voletile 只可见,不提供互斥,而 count++ 实际上是3个动作,先读取count 值,然后+1 ,最后写回到count 值

所以,可能发生 2个(或多个)线程同时读取到 count 比如 6,然后同时在内存中计算出 7,最后都写回7.这样6经过2次自增,结果却是7 。多次循环下来,最后结果就是不到10000

这样的需求,就只能使用同步,或者锁, 或者 原子类。

综上,如果需要多线程,一定要注意互斥性。如果只需要可见,则需要 volatile 可见性。如果无法确认,多数时候,还是用互斥比较稳妥,至少保证程序不出错。

多线程编程中一定要注意,并且,这种bug 非常难以处理。在debug 环境下,往往无法复现真正的多线程中的大量并发,也就很难复现这样的错误。

相关文章:

并发——同步访问共享的可变数据

关键字 synchronized 可以保证在同一时刻&#xff0c;只有一个线程可以执行某一个方法&#xff0c;或者某一段代码块。许多程序员把同步的概念仅仅理解为一种互斥的方式。即&#xff0c;当一个对象被一个线程修改的时候&#xff0c;可以阻止另一个线程观察到内部不一致的状态。…...

Docker网络模型(九)禁用容器网络

禁用容器网络 如果你想完全禁用容器上的协议栈&#xff0c;你可以在启动容器时使用 --network none 标志。在容器内&#xff0c;只有回环设备被创建。下面的例子说明了这一点。 创建容器 $ docker run --rm -dit \--network none \--name no-net-alpine \alpine:latest \ash通…...

JavaScript 教程---互联网文档计划

学习目标&#xff1a; 每天记录一章笔记 学习内容&#xff1a; JavaScript 教程---互联网文档计划 笔记时间&#xff1a; 2023-6-5 --- 2023-6-11 学习产出&#xff1a; 1.入门篇 1、JavaScript 的核心语法包含部分 基本语法标准库宿主API 基本语法&#xff1a;比如操作符…...

做好功能测试需要的8项基本技能【点工进来】

功能测试是测试工程师的基础功&#xff0c;很多人功能测试还做不好&#xff0c;就想去做性能测试、自动化测试。很多人对功能测试的理解就是点点点&#xff0c;如何自己不用心去悟&#xff0c;去研究&#xff0c;那么你的职业生涯也就停留在点点点上了。在这里&#xff0c;我把…...

在弹出框内三个元素做水平显示

最终效果图要求是这样&#xff1a; js代码&#xff1a; // 显示弹出窗口 function showPopup(node) {var popup document.createElement(div);popup.className popup;var inputContainer1 document.createElement(div);/* inputContainer1.className input-container1; */…...

纠删码技术在vivo存储系统的演进【上篇】

作者&#xff1a;vivo 互联网服务器团队- Gong Bing 本文将学术界和工业界的纠删码技术的核心研究成果进行了相应的梳理&#xff0c;然后针对公司线上存储系统的纠删码进行分析&#xff0c;结合互联网企业通用的IDC资源、服务器资源、网络资源、业务特性进行分析对原有纠删码技…...

如何实现APP自动化测试?

APP测试&#xff0c;尤其是APP的自动化测试&#xff0c;在软件测试工程师的面试中越来越会被问到了。为了更好的回答这个问题&#xff0c;我今天就给大家分享一下&#xff0c;如何进行APP的自动化测试。 一、为了实现JavaAppiumJunit技术用于APP自动化测试&#xff0c;所以需要…...

​​INNODB和MyISAM区别

1 存储引擎是MyISAM 如下&#xff1a; CREATE table test_myisam (cli int ) ENGINEMyISAM 存储目录里会有三个文件 test_myisam.frm为“表定义”&#xff0c;是描述数据表结构的文件 test_myisam.MYI文件是表的索引 test_myisam.MYD文件是表的数据 2 存储引擎是INNODB…...

普中自动下载软件1.86下载程序失败案例

今天在用开发板做一个功能&#xff0c;下载的时候报错了&#xff0c;说芯片超时 确定驱动安装好了的 波特率也试了一圈 线也换过了 最后发现是芯片类型选错了&#xff0c;这个开发板是用的stc89c52,所以我选了图里这个&#xff0c;但是翻了开发板配套的资料&#xff0c;发现…...

JavaScript HTML DOM

JavaScript HTML DOM&#xff08;文档对象模型&#xff09;是一种用于访问和操作HTML文档元素的编程接口。它将HTML文档表示为一个树形结构&#xff0c;使开发人员可以使用JavaScript来操作和修改HTML元素、属性、样式和事件。 通过使用HTML DOM&#xff0c;你可以使用JavaScr…...

solr快速上手:配置IK中文分词器(七)

0. 引言 solr作为搜索引擎&#xff0c;常用在我们对于搜索速度有较高要求且大数据量的业务场景&#xff0c;我们之前已经配置过英文分词器&#xff0c;但是针对中文分词不够灵活和实用&#xff0c;要实现真正意义上的中文分词&#xff0c;还需要单独安装中文分词器 solr快速上…...

【软件测试】接口测试工具APIpost

说实话&#xff0c;了解APIpost是因为&#xff0c;我的所有接口相关的文章下&#xff0c;都有该APIpost水军的评论&#xff0c;无非就是APIpost是中文版的postman&#xff0c;有多么多么好用&#xff0c;虽然咱也还不是什么啥网红&#xff0c;但是不知会一声就乱在评论区打广告…...

第六章 假言:那么、就、则;才。

第六章 假言&#xff1a;那么、就、则&#xff1b;才。 第一节 假言-公式化转换-等价矛盾 真题&#xff08;2012-38&#xff09;-假言-A→B的公式化转换-A→B的等价命题&#xff1a;①逆否命题&#xff1a;非B→非A。 38.经理说&#xff1a;“有了自信不一定赢。”董事长回…...

[干货] 如何解决慢SQL?详细分析和优化实践!

慢SQL优化实践 本篇博客将分享如何通过慢SQL分析工具和常用优化手段&#xff0c;来解决慢SQL的问题。首先让我们看一下慢SQL的定义。 什么是慢SQL 简单来说&#xff0c;慢SQL指的是执行时间较长的SQL语句。在数据库中&#xff0c;一个查询的运行时间往往会受到多种因素的影响…...

数据库实验三 数据查询二

任务描述 本关任务&#xff1a;查询来自借阅、图书、读者数据表的数据 为了完成本关任务&#xff0c;你需要掌握&#xff1a; 如何多表查询 相关知识 查询多个数据表 在实际应用中&#xff0c;查询经常会涉及到几个数据表。 基于多个相关联的数据表进行的查询称为连接查询…...

论文笔记与实战:对比学习方法MOCO

目录 1. 什么是MOCO2. MOCO是干吗用的3. MOCO的工作原理3.1 一些概念1. 无监督与有监督的区别2. 什么是对比学习3. 动量是什么 3.2 MOCO工作原理1. 字典查找2. 如何构建一个好的字典3. 工作流程 3.3 &#xff08;伪&#xff09;代码分析 4. 其他一些问题5. MOCO v2和MOCO v35.1…...

大数据Doris(三十八):Spark Load 导入Hive数据

文章目录 Spark Load 导入Hive数据 一、Spark Load导入Hive非分区表数据 1、在node3hive客户端&#xff0c;准备向Hive表加载的数据 2、启动Hive&#xff0c;在Hive客户端创建Hive表并加载数据 3、在Doris中创建Hive外部表 4、创建Doris表 5、创建Spark Load导入任务 6…...

【Prometheus】mysqld_exporter采集+Grafana出图+AlertManager预警

前提环境&#xff1a;已经安装和配置好prometheus server 所有组件对应的版本&#xff1a; prometheus-2.44.0 mysqld_exporter-0.14.0 grafana-enterprise-9.1.2-1.x86_64.rpm alertmanager-0.25.0 prometheus-webhook-dingtalk-2.1.0 简介 mysql_exporter是用来收集MysQL或…...

softmax 函数

https://blog.csdn.net/m0_37769093/article/details/107732606 softmax 函数如下所示&#xff1a; y i exp ⁡ ( x i ) ∑ j 1 n exp ⁡ ( x j ) y_{i} \frac{\exp(x_{i})}{\sum_{j1}^{n}{\exp(x_j)}} yi​∑j1n​exp(xj​)exp(xi​)​ softmax求导如下&#xff1a; i j…...

【SpringMVC】拦截器和过滤器之间的区别

过滤器 拦截器 调用机制 基于函数的回调 基于反射机制(动态代理) 依赖关系 依赖Servlet容器 不依赖Servlet容器 作用范围 对几乎所有的请求起作用 只对action请求起作用 访问范围 不能访问action上下文、栈 可以访问action上下文、栈 action生命周期 中的调用次数…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

Ascend NPU上适配Step-Audio模型

1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统&#xff0c;支持多语言对话&#xff08;如 中文&#xff0c;英文&#xff0c;日语&#xff09;&#xff0c;语音情感&#xff08;如 开心&#xff0c;悲伤&#xff09;&#x…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...

Java数值运算常见陷阱与规避方法

整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...

基于Springboot+Vue的办公管理系统

角色&#xff1a; 管理员、员工 技术&#xff1a; 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能&#xff1a; 该办公管理系统是一个综合性的企业内部管理平台&#xff0c;旨在提升企业运营效率和员工管理水…...

掌握 HTTP 请求:理解 cURL GET 语法

cURL 是一个强大的命令行工具&#xff0c;用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中&#xff0c;cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...

WEB3全栈开发——面试专业技能点P7前端与链上集成

一、Next.js技术栈 ✅ 概念介绍 Next.js 是一个基于 React 的 服务端渲染&#xff08;SSR&#xff09;与静态网站生成&#xff08;SSG&#xff09; 框架&#xff0c;由 Vercel 开发。它简化了构建生产级 React 应用的过程&#xff0c;并内置了很多特性&#xff1a; ✅ 文件系…...