[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 转到合成>新合成以创建新合…...

【iOS】懒加载
文章目录 前言一、懒加载的意义二、懒加载的原理三、懒加载优缺点 前言 iOS懒加载(Lazy Loading)是一种延迟加载的技术,它允许在需要的时候才初始化对象或执行某些操作,而不是在对象创建的时候立即执行。懒加载主要用于优化应用程…...

《脱离“一支笔、一双手、一道力扣”困境的秘诀》:突破LeetCode难题的五个关键步骤
导言: 在解决LeetCode等编程题时,不少人会陷入“一支笔、一双手、一道力扣(LeetCode)做一宿”的困境。尽管已经掌握了相关知识和算法,但在实际挑战中却无从下手。本文将分享如何摆脱这一困境的秘诀,让你在面…...

基于jeecg-boot的任务甘特图显示
更多功能看演示系统 gitee源代码地址 后端代码: https://gitee.com/nbacheng/nbcio-boot 前端代码:https://gitee.com/nbacheng/nbcio-vue.git 在线演示(包括H5) : http://122.227.135.243:9888 基于项目的任务显…...

docker export,import后无法运行,如java命令找不到,运行后容器内编码有问题
为什么用docker export呢,😔~由于客户环境太恶心了,测试一次更是麻烦,所以什么都得在本地调试完成,争取每次测试上线一次通过才行,说多了都是泪。 由于踩坑几次了,每次都忘记,且每次…...

Web3教程| 什么是地址监控?如何使用地址监控追踪黑客地址?
在当今Web3世界里,保护个人资产安全至关重要。据报道在2023年上半年,Web3领域因黑客攻击事件造成的损失高达4.794亿美元。 此外,10多个公链遭受黑客攻击,其中以太坊链遭受的损失最多,约为2.87亿美元。这些黑客的存在迫…...

flask结合mysql实现用户的添加和获取
1、数据库准备 已经安装好数据库,并且创建数据库和表 create database unicom DEFAULT CHARSET utf8 COLLATE utf8_general_ci; CREATE TABLE admin( id int not null auto_increment primary key, username VARCHAR(16) not null, password VARCHAR(64) not null…...

阿里云服务器配置 内存,cpu等等
实例升配,https://help.aliyun.com/document_detail/25438.html?spma2c4g.11174283.6.780.2cbf4c070oeino#title-a5t-gg2-...

PHP注册、登陆、6套主页-带Thinkphp目录解析-【强撸项目】
强撸项目系列总目录在000集 PHP要怎么学–【思维导图知识范围】 文章目录 本系列校训本项目使用技术 上效果图主页注册,登陆 phpStudy 设置导数据库项目目录如图:代码部分:控制器前台的首页 其它配套页面展示直接给第二套方案的页面吧第三套…...

android Activity设置背景为半透明的时候会显示上一个activity的内容
在弹出PopupWindow时将当前Activity设置成了半透明: WindowManager.LayoutParams lp = this.activity.getWindow().getAttributes();lp.alpha = 0.5f; //0.0-1.0this...

Linux 网络收包流程
哈喽大家好,我是咸鱼 我们在跟别人网上聊天的时候,有没有想过你发送的信息是怎么传到对方的电脑上的 又或者我们在上网冲浪的时候,有没有想过 HTML 页面是怎么显示在我们的电脑屏幕上的 无论是我们跟别人聊天还是上网冲浪,其实…...