[JAVAee]线程安全
目录
线程安全的理解
线程不安全的原因
①非原子性
②可见性
③代码重排序
体会何为不安全的线程
保证线程安全
一个代码在多线程的环境下就很容易出现错误.
线程安全的理解
线程安全是什么呢?通俗的来讲,线程安全就是在多线程的环境下,代码的结果是符合我们预期的,就可以称这个线程是安全的.
线程不安全的原因
①非原子性
关于原子性:
原子是最小的粒子,不可被分割.所以,原子性就是代表一系列不能被分割的操作.
可以这样说,在一节开往学校的火车的10号车厢上.你因为喝了太多水,突然想上厕所.于是便走到10号车险的公共厕所上,开展了"观察厕所是否有人","打开厕所门","进入厕所","关闭厕所门","上锁","上厕所","解锁","打开厕所门","走出厕所","关闭厕所门"着这一系列的操作.
我们应该很容易理解这一系列操作有着原子性,既是是连续且不可被分割的吧.总不能在你进入厕所关上门后允许有人打开你的厕所门.
而上锁这一操作就很好的保持了这一系列的原子性,因为当你在厕所执行"任务"的时候,有人想要打开你的厕所门也进行不了这一操作.因为此时门被上锁了,是不可能被打开的.除非你在里面进行了解锁这一操作.
在java当中,原子性是一条语句吗?并不是的:
int n = 0;
n++;
像是上面的代码的"n++"语句,是不是就很容易被理解具有原子性.
java是一门高级编程语言,在其之下的称之为汇编语言.在java中我们只是看到简单的n++一条语句,而在汇编语言中他的代码大致逻辑是:
- 从内存把数据读取到cpu中
- 进行数据的更新
- 将新数据写回cpu中
因为进程里的线程的调度是具有随机性的,在你执行把数据更新完但还没有写回这一步的时候,调度到了另一个线程,而且新被调度到的线程也要使用这个变量.这时候就会发生不对等的情况.
②可见性
在我们线程的基础知识中提及到,同一个进程中的多个线程之间是具有关联性的,线程间也共享着同一个空间.在这一基础上:可见性指, 一个线程对共享变量值的修改,能够及时地被其他线程看到.
JMM内存模型:
JMM模型是一个抽象的逻辑型,规定了一个进程中的所有变量都要存储在主内存中,进程中的线程又是共享同一个空间,所以说同一个线程中的所有线程都可以访问到主内存.同时,进程中的线程又有一个单独的工作内存.
- 当线程要读取一个主内存中的共享变量时,先要把主内存中的共享变量拷贝到工作内存中,再从工作内存中读取此数据
- 当线程要更新一个主内存中的共享变量时,先要把主内存中的共享变量拷贝到工作内存中并进行更新拷贝过来的副本,再去更改主内存的共享变量

因为这个可见性的缘故,线程1要修改共享变量的时候,线程2的同一个变量的数据还没有得到更新.就会导致结果的偏差.
③代码重排序
JVM、CPU指令集会对代码进行优化
编译器对于指令重排序的前提是 "保持逻辑不发生变化". 这一点在单线程环境下比较容易判断, 但
是在多线程环境下就没那么容易了, 多线程的代码执行复杂程度更高, 编译器很难在编译阶段对代
码的执行效果进行预测, 因此激进的重排序很容易导致优化后的逻辑和之前不等价
体会何为不安全的线程
public class Test {public static int n = 0;public static void count(){n++;}public static void main(String[] args) throws InterruptedException {//线程0Thread thread0 = new Thread(() ->{for(int i = 0; i < 10000; i++){count();//每次调用,n+1.预取:线程0能使n加上10000次}});//线程1Thread thread1 = new Thread(() ->{for(int i = 0; i < 10000; i++){count();//每次调用,n+1.预取:线程1能使n加上10000次}});thread0.start();//启动thread1.start();//等到线程0,线程1执行完成才去打印thread0.join();thread1.join();//我们的预期是,线程0加上10000,线程1加上10000.n为20000System.out.println(n);}
}

出现的结果不符合我们期望,就是因为count方法中没有保持原子性,导致两个线程间同一数据读出和写出的步骤重合而最终的数据错误.

通俗的来说,在多线程环境下可能出现线程不安全的原因有:
- 线程是抢占式执行的,随机调度导致的
- 多个线程修改同一个变量,会出现可见性的问题
- 线程中的修改操作不是原子性的
保证线程安全
可以给一个代码块使用synchronized关键字进行修饰,达到了上锁的作用.保证其原子性
我们更新一下,在count方法上使用synchronized修饰.在每一个线程调用的时候,其他线程对于这个count方法都会变为阻塞状态,即不能调用这个方法.
public static synchronized void count(){n++;}
最后的结果,我们就可以很好的保证了预期结果的正确,达到了多线程环境下的安全.

相关文章:
[JAVAee]线程安全
目录 线程安全的理解 线程不安全的原因 ①非原子性 ②可见性 ③代码重排序 体会何为不安全的线程 保证线程安全 一个代码在多线程的环境下就很容易出现错误. 线程安全的理解 线程安全是什么呢?通俗的来讲,线程安全就是在多线程的环境下,代码的结果是符合我们预期的,就…...
ELK环境搭建——概况
Elastic Stack,核心产品包括 Elasticsearch、Kibana、Beats 和 Logstash等等。能够安全可靠地从任何来源获取任何格式的数据,然后对数据进行搜索、分析和可视化。 目录 一:Elasticsearch: 1.1 从数据中探寻各种问题的答案 1.1.1 定义您自己的搜索方式...
面试知识点整理
计算机的物理内存是有限的,所以操作系统在遇到内存不足时,会通过换页机制暂时把 某个进程未使用的内存中的数据搬移到硬盘上(比如 Linux 的 swap 分区),并在系统页表中 删除相应的表项。当该进程访问数据已经被搬移到硬…...
腾讯云服务器CVM计算型c6/c5实例CPU型号、处理器主频大全
腾讯云服务器CVM计算型C6、C5、C4、CN3、C3和C2实例,计算型C6云服务器CPU采用Intel Xeon Ice Lake处理器,主频3.2GHz,睿频3.5GHz,腾讯云服务器网分享更多计算型CVM云服务器CPU型号、处理器主频性能说明: 目录 云服务…...
vue3笔记-脚手架篇
第一章 基础篇 第二章 脚手架篇 vue2与vue3的一些区别 响应式系统: Vue 2 使用 Object.defineProperty 进行响应式数据的劫持和监听,它对数据监听是一项项的进行监听,因此,当新增属性发生变化时,它无法监测到&…...
数字的补数
题目: 对整数的二进制表示取反(0 变 1 ,1 变 0)后,再转换为十进制表示,可以得到这个整数的补数。 例如,整数 5 的二进制表示是 "101" ,取反后得到 "010" &…...
Taskfile demo
https://github.com/yangyang5214/blog/issues/1 makefile 很好用,但是有些语法我不会。 go-task yml & shell 不错,推荐 Taskfile.yml https://github.com/go-task/task/blob/main/.golangci.yml # go install github.com/go-task/task/v3/cmd/ta…...
MyBatis学习笔记之高级映射及延迟加载
文章目录 环境搭建,数据配置多对一的映射的思路逻辑级联属性映射association分布查询 一对多的映射的思路逻辑collection分布 环境搭建,数据配置 t_class表 t_stu表 多对一的映射的思路逻辑 多对一:多个学生对应一个班级 多的一方是st…...
小程序如何删除/上架/下架商品
在小程序中,产品的删除、上架和下架是常见的操作,可以根据实际需求来管理商品的展示与销售。下面将介绍如何在小程序中删除上架下架商品的具体步骤。 进入商品管理页面, 在个人中心点击管理入口,然后找到“商品管理”菜单并点击。…...
Failed to load local font resource:微信小程序加载第三方字体
加载本地字体.ttf 将ttf转换为base64格式:https://transfonter.org/ 步骤如下 将下载后的stylesheet.css 里的font-family属性名字改一下,然后引进页面里就行了,全局样式就放app.scss,单页面就引入单页面 注: .title…...
使用fastjson错误
说明:使用fastjson时,对象解析不成功,一直报错,但是json格式没有错; 错误信息:Method threw ‘com.alibaba.fastjson.JSONException’ exception. json数据是正确的 分析:注意看,fa…...
【GitOps系列】使用Kustomize和Helm定义应用配置
文章目录 使用 Kustomize 定义应用改造示例应用1.创建基准和多环境目录2.环境差异分析3.为 Base 目录创建通用 Manifest4.为开发环境目录创建差异 Manifest5.为预发布环境创建差异 Manifest6.为生产环境创建差异 Manifest 部署 Kustomize 应用部署到开发环境部署到生产环境 使用…...
Android kotlin高阶函数与Java lambda表达式介绍与实战
一、介绍 目前在Java JDK版本的不断升高,新的表达式已开始出现,但是在Android混淆开发中,kotlin的语言与Java的语言是紧密贴合的。所以Java lambda表达式在kotlin中以新的身份出现:高阶函数与lambda表达式特别类似。接下来我讲会先…...
自然语言处理实战项目13-基于GRU模型与NER的关键词抽取模型训练全流程
大家好,我是微学AI,今天给大家介绍一下自然语言处理实战项目13-基于GRU模型与NER的关键词抽取模型训练全流程。本文主要介绍关键词抽取样例数据、GRU模型模型构建与训练、命名实体识别(NER)、模型评估与应用,项目的目标是通过训练一个GRU模型…...
7.26 Qt
用QT制作一个登陆界面 运行代码 login.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QDebug> //信息调试类,用于输出 #include <QIcon> //图标类头文件 #include <QPushButton&…...
【MySQL】库和表的操作
目录 一、库的操作 1.1创建数据库 1.2创建数据库案例 1.3字符集和校验规则 (1)查看系统默认字符集以及校验规则 (2)查看数据库支持的字符集 (3)查看数据库支持的字符集校验规则 (4&…...
(五)RabbitMQ-进阶 死信队列、延迟队列、防丢失机制
Lison <dreamlison163.com>, v1.0.0, 2023.06.23 RabbitMQ-进阶 死信队列、延迟队列、防丢失机制 文章目录 RabbitMQ-进阶 死信队列、延迟队列、防丢失机制死信队列延迟队列延迟队列介绍**延迟队列_死信队列_的实现**延迟队列_插件实现下载插件RabbitMQ 配置类RabbitMQ …...
windows下面的python配置
安装包选择exe后缀的 链接:https://pan.baidu.com/s/1sTzQdHMqI4KZwyJHl79Q3w 提取码:1111 PIP安装脚本 python版本pip安装脚本下载地址n3.6https://bootstrap.pypa.io/pip/3.6/get-pip.py3.7及以上https://bootstrap.pypa.io/get-pip.py 控制面板新…...
vue3中 状态管理pinia得使用
在做项目中 vue2改造vue3项目时的vuex 发生得一些变化 vue3项目中 先看下 stores.jsimport { defineStore } from pinia 引入方法注册方法 import { getListFieldLevel } from ..api/index.jsexport const useScreenStore defineStore(screen, {state: () > ({fieldList:…...
如何使用 After Effects 导出摄像机跟踪数据到 3ds Max
推荐: NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 在本教程中,我将展示如何在After Effects中跟踪实景场景,然后将相机数据导出到3ds Max。 1. 项目设置 步骤 1 打开“后效”。 打开后效果 步骤 2 转到合成>新合成以创建新合…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
【Linux系统】Linux环境变量:系统配置的隐形指挥官
。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量:setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...
uniapp 实现腾讯云IM群文件上传下载功能
UniApp 集成腾讯云IM实现群文件上传下载功能全攻略 一、功能背景与技术选型 在团队协作场景中,群文件共享是核心需求之一。本文将介绍如何基于腾讯云IMCOS,在uniapp中实现: 群内文件上传/下载文件元数据管理下载进度追踪跨平台文件预览 二…...
