【高并发】32位多核CPU并发读写long型数据为何会出现诡异问题?看完这篇我懂了!

简介: 诡异的问题我们在32位多核CPU的计算机上以多线程的方式读写long类型的共享变量时,线程已经将变量成功写入了内存,但是重新读取出来的数据和之前写入的数据不一致,这到底是为什么呢?原因分析

诡异的问题

我们在32位多核CPU的计算机上以多线程的方式读写long类型的共享变量时,线程已经将变量成功写入了内存,但是重新读取出来的数据和之前写入的数据不一致,这到底是为什么呢?

原因分析

其实,造成这个问题的根本原因就是线程的原子性问题,而线程的原子性问题最终的“幕后黑手”是线程切换,如果能够禁用线程切换就能够解决这个问题了!在操作系统层面来看,操作系统做线程切换需要依赖CPU的中断机制,所以说,禁止CPU发生中断就能够禁止线程切换。

这种方案在单核CPU上是可行的,但是并不适合多核CPU。

其实,就分析为何在32位多核CPU上执行long型变量的写操作会出现诡异的Bug问题,我们需要从数据类型占用的存储空间来分析。long型变量是64位的,在32位CPU上执行写操作会被拆分成两次写操作(分别是写高32位和写低32位)。我们可以用下图来表示。

微信图片_20211118123423.jpg

32位单核CPU

在32位单核CPU场景下,同一时刻只有一个线程执行,禁止CPU中断,也就是说,在单核CPU上,操作系统不会重新调度线程,实际上,也就是禁止了线程切换。如果一个线程获取到CPU资源,就可以一直执行下去,直到线程结束为止。在这个线程中,对于long型变量的两次写操作,要么都被执行,要么都没有被执行,两次写操作具有原子性,不会出现写入的数据和读取的数据不一致的情况。

我们可以简单的使用下图来表示32位单核CPU写long型数据这个过程。


由上图我们可以看出,在32位单核CPU中,禁止了线程切换之后,所有的线程都是串行执行的,对于long型变量的两次写操作,要么都被执行,要么都没有被执行,两次写操作具有原子性,不会出现写入的数据和读取的数据不一致的情况。

32位多核CPU

在32位多核CPU场景下,同一时刻,可能有两个甚至更多的线程在同时执行。假设有两个线程分别是线程A和线程B,线程A执行在CPU-01上,线程B执行在CPU-02上,此时,禁用CPU中断,只能保证在每个CPU上执行的线程是连续的,并不能保证同一时刻只有一个线程执行,如果线程A和线程B同时写long型变量的高32位的话,那么,就有可能出现诡异的Bug问题,也就是说,明明已经将变量成功写入内存了,但是重新读取出来的数据却不是自己写入的!!

我们可以简单的使用下图来表示32位多核CPU并发写long型数据这个过程。

微信图片_20211118123453.jpg

由上图我们可以看出,在32位多核CPU中,如果有多个线程同时对long类型的数据进行写操作,即使中断CPU操作,也只能保证在每个CPU上执行的线程是连续的,并不能保证同一时刻只有一个线程执行。如果多个线程同时写long型变量的高32位的话,那么,就有可能出现诡异的Bug问题。

总结

long型变量是64位的,在32位CPU上执行写操作,会被拆分成写高32位和写低32位两部分,如果此时有多个线程同时写long型变量的高32位的话,就有可能出现诡异的Bug问题。

注意:不只是long型变量,在32位多核CPU上并发写64位数据类型的数据,都会出现类似的诡异问题!!!

如果觉得文章对你有点帮助,请微信搜索并关注「 冰河技术 」微信公众号,跟冰河学习高并发编程技术。

写在最后

大冰:这就是今天的主要内容了,今天的内容非常重要,它能够帮助你更加深刻的理解并发编程的原子性问题,小菜童鞋,回去后一定要好好复习下。


小菜:好的,大冰哥,回去我一定好好复习。

最后,附上并发编程需要掌握的核心技能知识图,祝大家在学习并发编程时,少走弯路。

微信图片_20211118123513.jpg

相关文章
|
2月前
|
Windows
【Azure App Service】对App Service中CPU指标数据中系统占用部分(System CPU)的解释
在Azure App Service中,CPU占比可在App Service Plan级别查看整个实例的资源使用情况。具体应用中仅能查看CPU时间,需通过公式【CPU Time / (CPU核数 * 60)】估算占比。CPU百分比适用于可横向扩展的计划(Basic、Standard、Premium),而CPU时间适用于Free或Shared计划。然而,CPU Percentage包含所有应用及系统占用的CPU,高CPU指标可能由系统而非应用请求引起。详细分析每个进程的CPU占用需抓取Windows Performance Trace数据。
103 40
|
6月前
|
开发框架 并行计算 算法
揭秘Python并发神器:IO密集型与CPU密集型任务的异步革命,你竟还傻傻分不清?
揭秘Python并发神器:IO密集型与CPU密集型任务的异步革命,你竟还傻傻分不清?
82 4
|
2月前
|
NoSQL 关系型数据库 MySQL
招行面试:高并发写,为什么不推荐关系数据?
资深架构师尼恩针对高并发场景下为何不推荐使用关系数据库进行数据写入进行了深入剖析。文章详细解释了关系数据库(如MySQL)在高并发写入时的性能瓶颈,包括存储机制和事务特性带来的开销,并对比了NoSQL数据库的优势。通过具体案例和理论分析,尼恩为读者提供了系统化的解答,帮助面试者更好地应对类似问题,提升技术实力。此外,尼恩还分享了多个高并发系统的解决方案及优化技巧,助力开发者在面试中脱颖而出。 文章链接:[原文链接](https://mp.weixin.qq.com/s/PKsa-7eZqXDg3tpgJKCAAw) 更多技术资料和面试宝典可关注【技术自由圈】获取。
|
5月前
|
监控 并行计算 数据处理
构建高效Python应用:并发与异步编程的实战秘籍,IO与CPU密集型任务一网打尽!
在Python编程的征途中,面对日益增长的性能需求,如何构建高效的应用成为了每位开发者必须面对的课题。并发与异步编程作为提升程序性能的两大法宝,在处理IO密集型与CPU密集型任务时展现出了巨大的潜力。今天,我们将深入探讨这些技术的最佳实践,助你打造高效Python应用。
78 0
|
5月前
|
缓存 负载均衡 API
抖音抖店API请求获取宝贝详情数据、原价、销量、主图等参数可支持高并发调用接入演示
这是一个使用Python编写的示例代码,用于从抖音抖店API获取商品详情,包括原价、销量和主图等信息。示例展示了如何构建请求、处理响应及提取所需数据。针对高并发场景,建议采用缓存、限流、负载均衡、异步处理及代码优化等策略,以提升性能和稳定性。
|
5月前
|
存储 缓存 NoSQL
大数据-38 Redis 高并发下的分布式缓存 Redis简介 缓存场景 读写模式 旁路模式 穿透模式 缓存模式 基本概念等
大数据-38 Redis 高并发下的分布式缓存 Redis简介 缓存场景 读写模式 旁路模式 穿透模式 缓存模式 基本概念等
143 4
|
5月前
|
开发框架 并行计算 .NET
脑洞大开!Python并发与异步编程的哲学思考:IO密集型与CPU密集型任务的智慧选择!
脑洞大开!Python并发与异步编程的哲学思考:IO密集型与CPU密集型任务的智慧选择!
57 1
|
6月前
|
算法 Java 程序员
解锁Python高效之道:并发与异步在IO与CPU密集型任务中的精准打击策略!
在数据驱动时代,高效处理大规模数据和高并发请求至关重要。Python凭借其优雅的语法和强大的库支持,成为开发者首选。本文将介绍Python中的并发与异步编程,涵盖并发与异步的基本概念、IO密集型任务的并发策略、CPU密集型任务的并发策略以及异步IO的应用。通过具体示例,展示如何使用`concurrent.futures`、`asyncio`和`multiprocessing`等库提升程序性能,帮助开发者构建高效、可扩展的应用程序。
267 0
|
7月前
|
存储 缓存 数据处理
计算机临时存储CPU运算数据
【8月更文挑战第4天】
130 8
|
8月前
|
NoSQL Redis 开发工具
Redis性能优化问题之检查 Redis 实例是否启用了透明大页机制,如何解决
Redis性能优化问题之检查 Redis 实例是否启用了透明大页机制,如何解决