位置: IT常识 - 正文

多线程的风险 --- 线程安全(多线程的弊端)

编辑:rootadmin
多线程的风险 --- 线程安全

推荐整理分享多线程的风险 --- 线程安全(多线程的弊端),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:多线程的风险,多线程处理方式,多线程的弊端,多线程可能出现的问题,多线程可能出现的问题,多线程的风险,多线程的风险,多线程的风险,内容如对您有帮助,希望把文章链接给更多的朋友!

✨个人主页:bit me👇 ✨当前专栏:Java EE初阶👇 ✨每日一语:低头赶路,敬事如仪;自知自心,其路则明。

目 录

🍸一. 线程不安全🍹二. 线程不安全的原因🍸一. 线程不安全

多线程编程,最重要,也是最困难的问题就是线程安全问题,它的万恶之源,罪魁祸首就是调度器的随机调度 / 抢占式执行 这个过程

线程不安全:在随机调度之下,程序执行有多种可能,其中的某些可能导致代码出现了 bug ,线程不安全 / 线程安全问题

例如:两个线程对一个变量进行并发的自增(创建俩线程,让这俩线程同时并发的对一个变量,自增 5w 次,最终预期能一共自增 10w 次)

//创建俩线程,让这俩线程同时并发的对一个变量,自增 5w 次,最终预期能一共自增 10w 次class Counter{ //用来保存计数的变量 public int count; public void increase(){ count++; }}public class Demo14 { //这个实例用来进行累加 public static Counter counter = new Counter(); public static void main(String[] args) { Thread t1 = new Thread(()->{ for (int i = 0; i < 50000; i++) { counter.increase(); } }); Thread t2 = new Thread(()->{ for (int i = 0; i < 50000; i++) { counter.increase(); } }); t1.start(); t2.start(); try { t1.join(); t2.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("count: " + counter.count); }}

运行结果:

再运行一次:

发现随机调度顺序不一样,结果也就不一样

那上面的 bug 如何出现的?

执行一段代码,需要让 CPU 把对应的指令从内存中读取出来,然后再执行   像 count++ 一行代码,对应三个机器指令

1.从内存读取数据到 CPU(load)2.在 CPU 寄存器中,完成加法运算(add)3.把寄存器的数据写回到内存中(sava)多线程的风险 --- 线程安全(多线程的弊端)

指令的排序方式:

上述两种指令的排序方式恰好能到 2 。但是还有许许多多的排列组合方式,就都不一定了。

此时总和就是 1 了

这些还有许许多多就不在此举例了

根据上述的总结,俩种极端情况就是 5w 和 10w 。然后其他的情况就是 5w 和 10w 之间了。

拓展:

操作系统中的随机调度严格意义上来说其实不是 “随机调度” 。在内部他有自己的一套调度过程,我们不需要理解这个过程,了解了也无法改变这个调度。

🍹二. 线程不安全的原因

1. 操作系统的随机调度 / 抢占式执行。【罪魁祸首,万恶之源】 2. 多个线程修改同一个变量。【三个条件缺一不可,别的情况都没事儿】(所以写代码中可以针对这三个点进行改变进行规避,但是范围有限,不是所有的场景都可以规避掉) 3. 有些修改操作,不是原子的!【不可拆分的最小单位,就叫原子】

通过 = 来修改,= 只对应一条机器指令,视为是原子的 通过 ++ 来修改,++ 对应三条机器指令,则不是原子的

什么是原子性?   我们把一段代码想象成一个房间,每个线程就是要进入这个房间的人。如果没有任何机制保证,A进入房间之后,还没有出来;B 是不是也可以进入房间,打断 A 在房间里的隐私。这个就是不具备原子性的。   那我们应该如何解决这个问题呢?是不是只要给房间加一把锁,A 进去就把门锁上,其他人是不是就进不来了。这样就保证了这段代码的原子性了。(后续详解关于锁)   后果:如果一个线程正在对一个变量操作,中途其他线程插入进来了,如果这个操作被打断了,结果就可能是错误的。

4. 内存可见性,引起的线程安全问题。【内存改了,但是在优化的背景下,读不到看不见】

例如一个线程读,一个线程修改:线程 1 LOAD 之后需要进行 TEST ,然后继续 LOAD 再继续 TEST ,这样循环走下去,但是,在程序运行过程中,可能会涉及到一个操作 “优化” (可能是编译器 Javac,也可能是 JVM Java,也可能是操作系统),由于 LOAD 读的操作太慢,反复读,每次读到的数据都是一样的,JVM 就对此做出了优化,不需要重复在内存中读取了,直接就重复用第一次从内存读到寄存器的数据就好了,此时在优化之后,线程 2 突然写了一个数据,由于线程 1 已经优化成读寄存器了,因此线程 2 的修改线程 1 感知不到。   上述优化在单线程环境下没问题,但是多线程情况下就可能产生问题,多线程环境太复杂,编译器/JVM/操作系统进行优化的时候就可能产生误判!!!针对这个问题,Java 引入了 volatile 关键字,让程序猿手动禁止编译器针对某个变量进行上述优化!

5. 指令重排序。【调整代码执行顺序】

也是编译器 / JVM / 操作系统优化   优化在单线程环境下没问题,但是多线程情况下就可能产生问题,例如 Test t = new Test(); 在底层就有三个步骤:

创建内存空间往这个内存空间上构造一个对象把这个内存的引用赋值给 t

  此处就容易出现指令重排序引入的问题,2 和 3 的顺序是可以调换的,在单线程下调换这俩是没影响的,多线程下就不行了。例如我们俩线程,第一个线程按照先 2 后 3 的顺序,另一个线程尝试读取 t 的引用,当第二个线程读到 t 为非 null 的时候,此时 t 就一定是一个有效对象!!!如果是按照先 3 后 2 的顺序,第二个线程读到 t 为非 null 的时候,仍然可能是一个无效对象!!!

本文链接地址:https://www.jiuchutong.com/zhishi/298553.html 转载请保留说明!

上一篇:蓝桥杯第十四届蓝桥杯模拟赛第三期考场应对攻略(C/C++)(蓝桥杯第十四届模拟赛第三期)

下一篇:uni-app--》如何制作一个APP并使用?(uni-app编译)

  • 支付宝自动支付在哪里关闭(如何取消xbox的支付宝自动支付)

    支付宝自动支付在哪里关闭(如何取消xbox的支付宝自动支付)

  • 微信恢复默认灰色背景(微信恢复默认灰色模式)

    微信恢复默认灰色背景(微信恢复默认灰色模式)

  • qq电话和微信电话能同时打吗(qq电话和微信电话哪个省流量)

    qq电话和微信电话能同时打吗(qq电话和微信电话哪个省流量)

  • 微信语音转文字失败怎么解决(微信语音转文字识别不出来怎么办)

    微信语音转文字失败怎么解决(微信语音转文字识别不出来怎么办)

  • 华为手机怎么调亮度(华为手机怎么调时间和日期)

    华为手机怎么调亮度(华为手机怎么调时间和日期)

  • 现在苹果5c还能干什么(苹果5c还能下载软件吗)

    现在苹果5c还能干什么(苹果5c还能下载软件吗)

  • 华为畅享9怎样开启语音助手(华为畅享9怎样恢复出厂设置)

    华为畅享9怎样开启语音助手(华为畅享9怎样恢复出厂设置)

  • v1932a是vivo什么型号(v1932a是什么手机)

    v1932a是vivo什么型号(v1932a是什么手机)

  • 金羚洗衣机e2是什么故障(金羚洗衣机e2是什么故障维修视频)

    金羚洗衣机e2是什么故障(金羚洗衣机e2是什么故障维修视频)

  • 华为p30呼叫转移怎么设置(华为p30呼叫转移在哪里)

    华为p30呼叫转移怎么设置(华为p30呼叫转移在哪里)

  • 怎么取消充电保护模式(取消充电保护)

    怎么取消充电保护模式(取消充电保护)

  • 手机静音微信语音电话能听到吗(手机静音微信语音电话来电有声音吗)

    手机静音微信语音电话能听到吗(手机静音微信语音电话来电有声音吗)

  • 云下载是什么(云下载是正版windows吗)

    云下载是什么(云下载是正版windows吗)

  • 为什么打开word编辑不了(为什么打开word是兼容模式)

    为什么打开word编辑不了(为什么打开word是兼容模式)

  • 华为自动锁屏时间设置(华为自动锁屏时间怎么设置不了了)

    华为自动锁屏时间设置(华为自动锁屏时间怎么设置不了了)

  • 快手怎么找回被删作品(快手怎么找回被删除的头像)

    快手怎么找回被删作品(快手怎么找回被删除的头像)

  • word怎么设置每页字数(word怎么设置每行字数)

    word怎么设置每页字数(word怎么设置每行字数)

  • word中的上标怎么弄(word的上标怎么打)

    word中的上标怎么弄(word的上标怎么打)

  • 华为手表健康三环啥意思(华为手表健康三环代表什么)

    华为手表健康三环啥意思(华为手表健康三环代表什么)

  • 华为nova5耳机插口在哪里(华为nova5耳机插上没反应但可以充电)

    华为nova5耳机插口在哪里(华为nova5耳机插上没反应但可以充电)

  • web2.0名词解释(javaweb名词解释)

    web2.0名词解释(javaweb名词解释)

  • 电脑变慢了 如何解决(电脑较慢怎么办)

    电脑变慢了 如何解决(电脑较慢怎么办)

  • hpztsb09.exe是什么进程 有什么作用 hpztsb09进程查询(hppusg.exe是什么进程)

    hpztsb09.exe是什么进程 有什么作用 hpztsb09进程查询(hppusg.exe是什么进程)

  • Web项目部署环境搭建:JDK + Tomcat + IDEA +MySQL(java web项目部署)

    Web项目部署环境搭建:JDK + Tomcat + IDEA +MySQL(java web项目部署)

  • 车船税征收标准表
  • 一般纳税人如何做账报税
  • 混合销售行为的基本特征不包括
  • 汇算清缴期间发生的计入当期损益吗
  • 企业给员工的福利取消了可以劳动仲裁么
  • 员工产假个税系统改为非正常要更正申报吗?
  • 超市的库存商品分类混乱怎么看出来的
  • 发票验旧日期是什么意思
  • 车辆补贴的钱最快多久到账
  • 2020劳务退税怎么退
  • 房地产企业净利润为负的原因
  • 可供出售金融资产是指什么
  • 开发间接费什么时候计提
  • 无形资产 减值
  • 银行 收美金
  • 暂估入库的材料需要做T型账户嘛?
  • 增值税税率征收率变化时间节点
  • 印花税按主营业务成本计算吗
  • 房租发票进项税额抵扣
  • 房产企业可计入开发成本的利息如何确定?
  • 额外收入如何避税
  • 年终奖金计税方式区别
  • 贴息贷款利息怎么入账
  • 私募证券投资如何交易
  • 未开票收入冲回如何做账
  • le启动exe是什么意思
  • 绿化园艺
  • 股票交易税怎么算出来的
  • PHP:pcntl_get_last_error()的用法_PCNTL函数
  • 装饰工程公司主要做什么
  • 小规模纳税人销售自己使用过固定资产
  • php获取访问用户的ip
  • 小满Vue3第三十六章(Vue如何开发移动端)
  • 手撕发票怎样盖章子
  • 外汇申报是什么意思
  • postman操作流程
  • reprovision签名失败error
  • 企业购进固定资产,在安装完工交付使用时
  • 结转完工产品成本的会计分录
  • 自费出版违法吗
  • 结构性存款随时可取么
  • 未开票金额怎么报税
  • 购进销售农产品正常损耗怎么算
  • 免征企业所得税的有哪些行业
  • phpcms生成html
  • 应收处理的两大内容是什么
  • 小规模纳税人工资薪金怎么申报
  • 辅助账簿属于会计档案吗
  • 存货报废应如何进行账务处理
  • 什么是企业汇算清缴年度
  • 红字发票什么意思怎么做账
  • 营改增阶段
  • 政府扶持资金的优缺点
  • 产品检验费怎样计算
  • 公司租赁办公场所,没发票怎么办
  • 总账科目有应交税费对吗
  • 公司有美金账户如何做账
  • 本月暂估入库,下月
  • 包装物报废收回残料
  • 质保金可以先不开票吗
  • 总部结算什么意思
  • 库存商品盘点流程
  • 免征增值税进项税怎么弄
  • 微软9月30日将发行股票
  • vs2015无法启动程序exe
  • 新手教程进不去
  • win10正版和盗版区别大吗
  • win8系统触摸板按键不能用
  • 常见的错误方法
  • cocos2d-x教程
  • python数字图像处理库
  • Linux文本处理工具的实验总结
  • unity增加组件
  • unity资源包管理器
  • javaScript parseInt字符转化为数字函数使用小结
  • jquery作品
  • python操作json字符串
  • 重庆地方税务局刘飞虎
  • 江苏网上税务局官网登录
  • 江西省国家税务局李德平
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设