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

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

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

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

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

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

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

相关推荐
知无不研32 分钟前
lambda表达式的使用(3)
开发语言·c++·lambda
数智化管理手记42 分钟前
海量数据如何沉淀有效数据资产?数据标准化治理方案如何搭建?
java·大数据·人工智能
cfm_29141 小时前
SpringAI + Ollama 本地大模型
java·开发语言·人工智能·语言模型
鲸采云SRM采购管理系统2 小时前
采购管理系统哪家好?2026最新测评对比
java·服务器·数据库
C++ 老炮儿的技术栈2 小时前
基于Qt实现轻量化本地音乐播放器
开发语言·c++·qt·c·播放器·音乐
qq_448011162 小时前
C语言中的柔性数组
c语言·开发语言·柔性数组
小白学大数据2 小时前
长周期爬虫的数据一致性:断点续爬 + 事务回滚保障采集质量
开发语言·爬虫·测试工具
0x533 小时前
Java网络编程(二)
java·服务器·网络
zlinear数据采集卡3 小时前
D223上位机C#开发实战:从帧解析到波形显示的完整实现
开发语言·arm开发·嵌入式硬件·fpga开发·开源·c#
Flittly3 小时前
【雕虫大技】Agent 动态 Skill 供应链安全加固(三):输出校验与治理闭环实战
java·spring boot·spring