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

线程安全问题

下面用一个简单的银行账户转账例子,结合代码和图示说明多线程安全问题的四个必要因素:

一、临界资源共享(共享账户)

public class BankAccount {private int balance = 1000; // 共享资源:账户余额public void transfer(int amount) {balance = balance - amount; // 写操作:转出金额}
}
  • 问题:多个线程同时调用transfer()修改balance,导致数据冲突。

二、线程切换(操作交错)

假设两个线程同时执行transfer(500)

// 线程A执行(时间线1)
1. 读取balance = 1000
2. 计算1000 - 500 = 500// 此时线程A被CPU调度挂起...// 线程B执行(时间线2)
3. 读取balance = 1000(因为线程A未写入新值)
4. 计算1000 - 500 = 500
5. 写入balance = 500// 线程A恢复执行
6. 写入balance = 500(覆盖线程B的结果)
  • 结果:两次转出500元后,余额应为0,但实际仍为500元。

三、原子性操作缺失(非原子的写)

balance = balance - amount分解为三个步骤:

  1. 读取balance的值
  2. 计算balance - amount
  3. 将结果写回balance

非原子性导致步骤间可能被其他线程打断。

四、内存可见性问题(缓存不一致)

public class BankAccount {private int balance = 1000; // 未声明volatile,存在可见性问题public void transfer(int amount) {balance = balance - amount;}
}
  • 场景
    1. 线程A将balance缓存到CPU寄存器。
    2. 线程B修改主内存中balance的值。
    3. 线程A继续使用寄存器中的旧值,导致计算错误。

解决方案示例(破坏必要因素)

public class BankAccount {private volatile int balance = 1000; // 用volatile保证可见性public synchronized void transfer(int amount) { // 用synchronized保证原子性balance = balance - amount;}
}
  • 原理
    • synchronized保证同一时间只有一个线程执行transfer()(破坏竞争条件)。
    • volatile保证每次读取都从主内存获取最新值(解决可见性问题)。

总结

必要因素示例中的体现解决方案
临界资源共享多个线程共享balance变量避免共享(如使用ThreadLocal)
线程切换线程执行过程中被CPU调度用锁(synchronized)强制串行化
原子性操作缺失balance = balance - amount非原子用原子类(AtomicInteger)或锁
内存可见性问题线程间缓存数据不同步用volatile或锁保证内存同步
http://www.xdnf.cn/news/588475.html

相关文章:

  • 100个Linux运维知识
  • Cursor远程连接+工具使用
  • VSCode查询
  • 人工智能如何改变医疗健康行业?
  • 门店自检数字化解决方案:智能任务派发+AI复核实践
  • Strace:深入系统调用的强大调试工具
  • 手机打电话时由对方DTMF响应切换多级IVR语音菜单(完结)
  • PyTorch中diag_embed和transpose函数使用详解
  • 小白的进阶之路系列之三----人工智能从初步到精通pytorch计算机视觉详解上
  • vue2使用pdfmake
  • Qt无边框界面添加鼠标事件
  • 吃透 Golang 基础:数据结构之切片
  • 实现了TCP的单向通信
  • 【数据库】-2 mysql基础语句(上)
  • 旋转编码器计次 红外对射传感器计次小实验及其相关库函数详解 (江协科技)
  • 第四章:YOLOv11 实战应用与开发指南
  • LeetCode 404.左叶子之和的迭代求解:栈结构与父节点定位的深度解析
  • 力扣.H指数力扣.字母异位词力扣.289生命游戏力扣452.用最小数量的箭引爆气球力扣.86分隔链表力扣.轮转数组
  • 高等数学-常微分方程
  • 国产三维CAD皇冠CAD(CrownCAD)建模教程:交流发电机
  • 推荐一个Excel与实体映射导入导出的C#开源库
  • 手写简单的tomcat
  • (泛函分析)线性算子连续必有界的证明
  • GraphRAG使用
  • 动态规划(七)——子数组系列(求和问题)
  • labview实现将百分制分数转换为等级制分数
  • Vue 3 官方 Hooks 的用法与实现原理
  • ai外呼平台:AnKo打造高效多模型服务体验!
  • labview实现LED流水灯的第二种方法
  • 每日算法刷题计划day13 5.22:leetcode不定长滑动窗口最短/最小1道题+求子数组个数越长越合法2道题,用时1h