栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

线程不安全的原因

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

线程不安全的原因

1.线程的抢占式执行过程

线程的执行顺序不是固定的。哪个线程先抢到CPU就执行,哪怕是其中一个线程正在执行时,其他线程若是抢到了CPU,就会打断前一个的过程,先执行自己的。

2.多个线程修改同一个变量

比如两个线程都想对变量m=0进行加一操作,正常的话,m在两次加一之后应该变成2,但是由于线程的抢占式执行过程,线程二有可能在线程一刚刚读取m之后就开始执行,也从内存中读取m,此时线程一和线程二手中的m的值都为0,两个线程执行完毕之后m都为1,将m又存入内存,此时内存中的m=1,所以就出现了线程安全问题。

3.修改操作不是原子的

线程的修改操作不是原子性的,也就是说不是一个整体,线程的执行过程是可能被穿插的。线程二可能在线程一正在执行时,抢占CPU,打断线程一的执行。
就比如:你想吃苹果,你先拿去清洗,洗完之后,碰到你朋友,他也想吃,就把苹果从你手中抢过去吃了,他吃了几口觉得不想吃了,又把苹果还给你,这个时候你才能继续完成吃苹果这个最终过程。

4.内存可见性

本质:操作内存比操作缓存要慢很多,编译器的优化导致线程一修改的数据没有及时存入内存,线程二就读不到最新的数据。

工作内存:CPU寄存器和缓存
主内存:真实内存

例如线程一对变量m=0循环自增10次,线程二对变量m加一;
正常情况线程一对m每次加一之后都应该把m放回主内存中,但由于编译器的优化,所以每次加一之后新的m的值放在了工作内存中,只有到最后一次加一之后,才会将m的值放入主内存中,。
但是如果线程二在线程一执行过程中就读取m,是从主内存中读取的,所以读到的m=0,并不是新更改后的值,所以就会造成线程安全问题。

5.指令重排序

编译器会调整执行顺序,在逻辑不变的情况下提高效率。
调整顺序,也可能会造成线程安全问题;

比如:我去取快递,顺便帮舍友买饭。但是因为食堂离得近,我就先去买饭,然后去取快递;买完之后,准备去取快递。但是舍友以为我先去取得快递,饭还没有买,她就说不用买了,她吃泡面。但是此时饭已经买了,所以就造成了冲突。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/272460.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号