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

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

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

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

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

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

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

相关推荐
光影6279 小时前
Python接口自动化测试----Requests库基础入门
开发语言·python·测试工具·pycharm·自动化
程序媛_9 小时前
【Python】连接PostgreSQL获取手机验证码
开发语言·python·postgresql
ch.ju9 小时前
Java Programming Chapter 4——Inherited call
java·开发语言
是有头发的程序猿9 小时前
竞品分析 + 用户洞察自动化|基于 item_review 评论接口 + 多 AI Agent 实现淘宝评论全量采集与智能分析(附python源码)
java·python·自动化
信看9 小时前
Jetson Orin Quectel QMI 拨号上网
开发语言·python
keykey6.9 小时前
LSTM 文本情感分析:从词嵌入到分类实战
开发语言·人工智能·深度学习·机器学习
凤凰院凶涛QAQ9 小时前
《Java版数据结构 & 集合类剖析》链表与LinkedList:节点手拉手,增删不用愁
java·数据结构·链表
数据知道9 小时前
网站到底是如何通过JS读取你的浏览器指纹的?
开发语言·javascript·ecmascript·指纹浏览器
c238569 小时前
C++的IO流深入理解(上)
开发语言·c++
SilentSamsara9 小时前
DuckDB + Python:嵌入式 OLAP 数据库的轻量分析实战
开发语言·数据库·python·微服务