当前位置: 首页 > news >正文

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

一、观察线程不安全

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。

http://www.cnnetsun.cn/news/114019.html

相关文章:

  • 《Java Web开发入门很简单》——学习笔记,新手入门,收藏这篇就够了
  • 2025年,国内外最火的10款降AI率工具亲测!(持续更新)
  • 基于大数据的餐饮食材管理系统的设计与实现开题报告
  • 基于大数据的交通信号智能控制系统的设计与实现开题报告
  • 基于大数据的交通信号智能控制系统的设计与实现任务书
  • 蜘蛛池站点优化思路分享
  • 2025 OA 选型关键看这 4 点:集成、灵活、安全、易用,附高性价比系统清单
  • 图神经网络与pytorch
  • Xiaomi 商城页面布局(部分)
  • FPGA以太网升级程序:便捷qspi Flash升级,具备校验功能,适用于Xilinx 7系列...
  • 运料小车装卸料控制:西门子1200PLC与TP700触摸屏联机仿真博途16
  • S32K311启动过程中,向量表重定向
  • 从蓝图到产线:高效产品信息传递的桥梁建设
  • 时间复杂度
  • 网站建设公司怎么选?2025年网站设计制作公司推荐指南
  • 今天咱们来聊一个挺有意思的优化算法改进——基于透镜成像反向策略的海洋捕食者算法。这个改进版本在原始MPA基础上搞了点新花样,咱们直接上干货看代码实现
  • Gitee:本土化DevOps平台如何重塑中国开发者生态
  • vCenter Server 8.0U3h 新增功能简介
  • Cisco NX-OS 10.6(2)F 发布 - 数据中心网络操作系统
  • Ubuntu24.04无操作卡死,无法唤醒问题以及内核版本切换记录
  • 全场景覆盖・全流程智控:分布式解决方案让多功能厅 “不止于多”
  • 【轨物方案】聚焦锯床设备智能化升级,打造工业互联网新范式
  • 【轨物交流】轨物科技亮相2025高校科技成果交易会
  • cesium加载geotiff的 四种方法
  • 【毕业设计】基于python的运维管理平台的设计与实现
  • 苹果 iOS 开发真正复杂的不是写代码这方面,是证书、构建、上架
  • FSMC-TFTLCD显示实验(5):显示一个字符串的函数传递过程追踪~
  • 基于Android的课程考勤及作业提交系统
  • 飞易通蓝牙与Wi-Fi模块:医疗产品无线连接的全能助手
  • 你的音效素材库该升级了!这个网站的分类细到超出你想象