线程安全问题的产生原因与解决方案

线程学习java过程中较难搬动的大山之一,但山再高总会搬完,路再远也总会走到。此篇是线程安全问题产生的原因与解决方案阐述,且看我慢慢"搬山"。

一.线程安全问题产生原因

1. 线程安全产生的根本原因是操作系统对线程的调度是随机的,线程是抢占式执行的;2.当多个线程同时修改同一变量,会产生线程安全问题(竞争同一资源,互相覆盖、干扰),但注意单个线程修改一个变量是不会产生线程安全问题的;3.单个线程修改操作不是原子的【例如:i++(读取i值,计算i值,更新i值)不是原子操作】,在多线程的情况下修改中可以被别的线程打断,造成线程安全问题;4. 内存可见性问题【一个线程修改了共享变量,但由于cpu缓存,另一线程并没有读取到更新后的值就是内存可见性问题】,会引起线程不安全问题;5.指令重排序问题【cpu或编译器为了跑得更快,对机器的指令的执行顺序重新进行排列优化,但多线程环境下,这种优化,会破坏线程间的执行次序与可见性(互相看不到对方指令被重排序了,会读到半初始化、顺序错乱的值),导致程序出现不符合预期的并发问题就是指令重排序问题】,会引起线程不安全问题。

二.线程安全问题的解决方案

1.线程安全问题的根本原因是我们无法左右的,我们能解决的只有他后面的原因。解决原因二可以通过调整代码结构(将变量变为局部变量或使用ThreadLocal为多个线程自动创建各自的变量或使用不可变对象)、使用锁、使用原子类。解决原因三主要方法是通过加锁,将非原子的操作打包成原子操作,一旦加锁使其它线程无法再加锁只能阻塞等待解锁(注意线程之间要产生互斥效果需要有同一个锁对象【锁对象一般用currentThread()获取,synchronized修饰static修饰的方法,相当于针对当前类对象进行加锁】)。解决原因四主要方法使用volatile关键字修饰变量,告诉编译器不要去优化,即对变量读取时不会被优化成读取寄存器【不在内存里读取,把变量优化到寄存器】,保证了每次都可以读到最新值,还有一种方法是加锁。解决原因五方法依旧是使用锁与volatile修饰变量【对这个变量的读写操作加屏障,禁止前面与后面的代码互相跨过去重排序】。加锁不可以解决根本原因但其它的原因【原子性、可见性、指令重排序】都可以解决。

本节复盘到此结束,🦀🦀(若有误,望告知,感谢大家!

相关推荐
leaves falling7 分钟前
Qt 项目:计算圆面积
开发语言·qt
xiaoye37088 分钟前
某大厂java面试题二面20260313
java·开发语言·spring
Full Stack Developme14 分钟前
Java -jar 命令 可以有哪些参数设置
java·开发语言·jar
独隅30 分钟前
Python `with` 语句 (上下文管理器) 深度解析与避坑指南
开发语言·python
做怪小疯子33 分钟前
Python 基础学习
开发语言·python·学习
一只程序熊37 分钟前
vite-cool-unix-ctx] Unexpected token l in JSON at position 0
java·服务器·前端
晨晖242 分钟前
idea2017的下载,破解及使用
java·ide·intellij-idea
denggun123451 小时前
结构化并发(Structured Concurrency)
开发语言·ios·swift
OKkankan1 小时前
红黑树的原理及实现
开发语言·数据结构·c++·算法
摇滚侠1 小时前
Java 项目教程《黑马商城-MQ 篇》,分布式架构项目,从开发到部署
java·分布式·架构