线程安全(重点)

目录

一、问题抛出

二、分析导致线程不安全的原因

1.线程的抢占式执行

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

3.原子性

4.内存可见性

5.指令重排序

总结

三、解决线程不安全的问题


一、问题抛出

当使用两个线程同时对一个变量自增5万次,预测结果是自增的和10万,但是代码正确的情况下,执行的结果随机且错误,这就是线程不安全造成的现象。

二、分析导致线程不安全的原因

1.线程的抢占式执行

线程的执行顺序并不是按照我们期望的顺序执行,这是线程不安全的主要原因,并且这个问题我们解决不了,完全由cpu随机调度。

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

多个线程修改不同变量不会出现线程不安全问题;多个线程读取同一个变量不会出现线程不安全问题;同一个线程读取或修改同一个变量不会出现线程不安全问题。

3.原子性

要么全都执行,要么全都不执行。

代码中的count++对应到cpu中有三条指令(读取、执行、写会)

由于cpu指令不是原子性的,因此三个指令都没有执行完就被cpu调度走了,导致其他的线程执行时没有读到上一个线程修改后的新值,最后结果出现错误。

4.内存可见性

JMM(Java Memory Model)Java内存模型

 每个工作内存都是独立的,相互之间不能访问。

内存可见性就是使相互之间能够访问,这样当我们在某一个工作内存中修改值时,其他线程也能感觉到。一般情况下,当我们不对变量做任何处理时不能达到能存可见性的效果。

5.指令重排序

编译器会将我们的代码进行进行强制重排(JAVA层面会重排,JVMC++层面会重排,CPU执行指令阶段也会重排)

指令重排在单线程环境下没有影响,且必须建立在结果正确的情况下,操作逻辑互不影响。

总结

造成线程不安全的主要原因:

1.线程的抢占式执行

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

3.原子性

4.内存可见性

5.有序性

三、解决线程不安全的问题

1.线程的抢占式执行   

CPU调度的方式,硬件层面无法解决

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

工作中需要并发编程提高效率,必须满足

3.原子性   

指令是在CPU上执行的,CPU执行不是原子性,我们可以通过某些指令使他满足原子性

4.内存可见性   

进程之间的内存是隔离的,而且有内存间通信的机制,那么线程之间也会有

5.有序性      

通过JAVA中一些关键字使程序不进行指令重排序

通过上面的分析,我们可以通过改变3 4 5点来使线程安全,而3 4 5 恰好就是JMM的主要特性,我们可以在JAVA层面解决线程不安全问题。

通过加锁的方式来满足3 4 5的原子性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LAKURRAA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值