news 2026/6/15 5:07:37

理解线程不安全:从观察到原因分析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
理解线程不安全:从观察到原因分析

一、观察线程不安全

public class UnsafeCounter { private static int counter = 0; public static void main(String[] args) throws InterruptedException { Thread[] threads = new Thread[10]; for (int i = 0; i < 10; i++) { threads[i] = new Thread(() -> { for (int j = 0; j < 100000; j++) { counter++; } }); threads[i].start(); } for (Thread t : threads) { t.join(); } System.out.println(counter); } }

如果你运行这个代码多次,你可能会发现输出结果总不是1000000。这是因为 counter++ 操作在 JVM 字节码中不是原子性的:它涉及读取值、递增、写回三个步骤。在多线程并发时,这些步骤可能被交织,导致数据丢失。

二、 线程不安全的概念

如果多线程环境下代码运⾏的结果是符合我们预期的,即在单线程环境应该的结果,则说这个程序是线程安全的。

三、线程不安全的原因

3.1线程调度是随机的

随机调度会导致一个程序在多线程的环境下,执行顺序会有很多变数,这是线程安全的罪魁祸首。

3.2修改共享数据

在多线程中,多个线程可能会修改同一个数据,这个共享数据就会导致线程不安全。

3.3原子性

原子性指的是一个操作(或一系列操作)被视为不可分割的整体:它要么完全执行成功,要么完全不执行,不能被中断或部分执行。

就如上面所说,count++在JVM字节码中就分解为(读取、递增和写回),如果在执行步骤期间切换线程就会出错。

3.4可见性

可见性指一个线程对共享变量的修改,其他线程能否立即看到。在 JVM 中,由于线程本地缓存和 CPU 缓存,一个线程的修改可能不立即刷新到主内存。

java内存模型

  • 线程之间的共享变量存在主内存
  • 每一个线程都有自己的"工作内存"
  • 当线程要读取一个共享变量的时候,会把变量从主内存拷贝到工作内存,再从工作内存读取数据
  • 当线程要修改一个共享变量的时候,也会修改内存中的副本,再同步回主内存

3.5指令重排序

3.5.1什么是指令重排序

指令重排序是指程序代码在源代码中的书写顺序,与实际执行时的顺序不一致的现象。这不是bug,而是为了优化执行效率而设计的特性。在Java中,这与Java内存模型(Java Memory Model,JMM)密切相关。JMM定义了线程如何通过内存交互,包括可见性、原子性和有序性(ordering)。有序性问题正是由指令重排序引起的。

3.5.2指令重排序的原因

主要目的是性能优化:

  • 减少等待时间
  • 缓存利用
  • 编译器优化

3.5.3示例

boolean flag = false; int data = 0; // 线程1 data = 42; flag = true; // 线程2 while (!flag) {} System.out.println(data); // 可能打印0

重排序可能先设置flag=true,再写data,导致线程2看到flag=true但data=0。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/14 5:13:43

什么是基于大模型的智能体构建?

在人工智能迅速发展的今天&#xff0c;大语言模型&#xff08;Large Language Models, LLMs&#xff09;已经从单纯的文本生成工具演变为推动新一代智能系统的核心引擎。基于大模型的智能体构建&#xff0c;正是这一技术浪潮中最具前景的方向之一。它不仅仅是让机器“说话”或“…

作者头像 李华
网站建设 2026/6/13 4:04:54

Java毕业设计-基于springboot开发的医院信管系统,从零到一构建项目,收藏这篇足够了

文章目录 前言一、毕设成果演示&#xff08;源代码在文末&#xff09;二、毕设摘要展示 1.开发说明2.需求分析3、系统功能结构 三、系统实现展示 1、系统功能模块2、管理员功能模块3、 医生功能模块 四、毕设内容和源代码获取总结 Java毕业设计-基于springboot开发的医院信管…

作者头像 李华
网站建设 2026/6/14 22:42:47

多线程核心:互斥与同步

在多线程开发中&#xff0c;互斥和同步是解决 “资源竞争” 与 “执行顺序” 问题的核心技术&#xff0c;本文结合原理 代码 图示详细解析。一、互斥&#xff08;Mutex&#xff09;&#xff1a;临界资源的排他性访问1. 基本概念临界资源&#xff1a;多线程中会被 “读写操作”…

作者头像 李华
网站建设 2026/6/12 17:29:37

选对老师,一次过!高项备考别再自己硬扛了!

选对老师&#xff0c;真的能改变备考的轨迹&#xff01;作为一个过来人&#xff0c;我太懂那种面对厚厚教材和抽象论文的无助感了。自己埋头苦学了大半年&#xff0c;知识点像一盘散沙&#xff0c;案例分析找不到逻辑&#xff0c;论文更是无从下手&#xff0c;差点就想放弃今年…

作者头像 李华
网站建设 2026/6/12 19:01:10

一文精通大数据行式存储的性能优化

一文精通大数据行式存储的性能优化&#xff1a;从原理到实战的全链路拆解 1. 引入与连接&#xff1a;为什么行式存储还需要优化&#xff1f; 1.1 一个真实的痛点场景 某电商平台的订单系统遇到了棘手问题&#xff1a; 运营同学要查用户「小A」最近30天的所有订单记录&#xff0…

作者头像 李华
网站建设 2026/6/13 3:34:31

健康管理实训室:解锁康养技能提升新路径

一、认知与评估起点&#xff1a;构建健康管理的专业基石健康管理实训室的首要环节&#xff0c;是培养学生精准的评估与认知能力。实训室内配备的老年综合评估系统、心理自助服务系统等专业工具&#xff0c;为学生提供了标准化的健康评估操作平台。通过这些系统&#xff0c;学生…

作者头像 李华