详析Java线程进程的并发问题

并发的前提条件
并发问题发生的前提条件一定是资源共享,这里的资源一般指的是数据,共享指的是多线程之间共享。
也就是只有在多线程共享资源的情况下才可能产生并发问题,这是并发问题产生的前提条件,在这个条件下,有可能产生并发问题,那么并发问题的根源究竟是什么呢?
cpu操作数据的基本机制
前面提到了并发的前提条件是数据共享,想了解并发问题的根源就需要知道cpu操作数据的基本原理;
数据存储包括这几个位置:磁盘、内存、缓存、寄存器;
寄存器可以认为是cpu的一部分,所以有的地方并没有将cpu和寄存器拆分讲解,通常来讲只需要知道cpu运算时都是从寄存器取数据,运算完成后再放回寄存器即可,cpu和寄存器之间没有其他任何中介。
缓存是cpu与寄存器之外的一层存储,但也是每一个cpu独立占有的一块内存区域,各个cpu缓存之间数据不可以共享。
内存是程序运行时数据的主要存放区域,内存数据是共享的,一般来讲,各个cpu都可以访问内存中的数据;
磁盘,数据最终持久化的存储;
cpu操作数据的流程一般是先由磁盘读到内存,再从内存读到缓存,再由缓存到寄存器进行运算;运算之后的结果直接写入寄存器,然后刷新到缓存,再刷新到内存,最后写入磁盘;
程序数据流图
并发问题的源头
了解了cpu运行机制之后,下面说并发问题的根源,主要是由于数据可见性、操作原子性、操作有序性这三个原因导致的;
什么是数据可见性?
通俗点来说就是cpu看到的数据并不是最新的数据,cpu读取数据是优先从缓存中读取,如果缓存中存在就使用缓存中的数据,假如数据被另一个cpu改变了,这时其他cpu中缓存数据就可能与内存中的数据不一致,也就是cpu没有看到并使用最新的数据,导致程序执行结果异常。
什么是操作原子性?
同一个cpu可以交替执行多个线程,不太了解的读者可以初步学习一下cpu时间片与线程调度的基本知识。
在同一个cpu,交替执行多个线程的时候,就可能出现线程中断,并且在中断过程中受其他线程影响而导致中断的线程恢复之后,执行逻辑异常。
比如:a线程执行count = count + 1操作,b线程也执行相同的操作;当a线程读取到count的值,并进行加1计算之后,还没写回到内存之前被中断,b线程完全执行了count = count + 1,count的值得到更新;这时a线程恢复(并不会重新读取并计算),将之前计算的值写回到缓存,导致count本来应该执行两次加1,但最终结果只加了一次1;
什么是操作有序性?
有序性指的是cpu执行代码的顺序和程序开发者定义的顺序不一致?为什么还会不一致呢?
编译器在将高级开发语言编译成计算机指令的时候,出于性能优化,可能会对代码执行重排序,cpu在执行指令的时候,也可能对代码重排序;当然重排序的前提是在单线程条件下的语义不变性,但不能保证多线程条件下语义也相同。
java单例模式中的双重校验锁,单例变量为什么要声明为volatile,就是为了解决指令重排序带来的问题,我们在下一章节进行详细讲解。感兴趣的也可以自行查阅资料学习。
并发问题的解决方案
并发问题不是java语言特有的,而是计算机运行原理与操作系统带来的,那么从计算机与操作系统层面来看,它们都提供了哪些解决方案来避免数据可见性、程序原子性、操作有序性的保障呢?java语言又是如何对这些方案进行封装的呢?开发者有哪些手段可以解决这些问题呢?

AI网红Andrej Karpathy最新力作,倾囊相授神经网络的33条训练技巧
海天雄电子CES-6818开发平台简介
路由器和网桥的区别
基于51单片机的遥控台灯系统设计
华为方舟编译器明天正式开源将支持20余款机型
详析Java线程进程的并发问题
对于将高电压输入转换成低电压输出的电源转换器,该如何提高效率
小度智能音箱发布,小爱同学慌了
厚植安全基石,国民技术创新赋能行业应用安全
一加8设计企划稿曝光 采用屏下开孔摄像头
恒讯科技介绍:网站服务器租用有哪些类型?
实际路测和虚拟测试相结合的方式来训练自动驾驶系统,到底两者如何融合?
pycharm怎么看程序运行到哪里了
国产铁电存储器PB85RS2MC可用于太阳能发电能量采集
基于一线总线和温度传感器DS18820实现智能建筑温度测试系统设计
关于区块链的一些基本知识你需要了解
电脑升级SSD后,依然卡顿怎么解决
华为P40前面板谍照疑似曝光,前置打孔摄像头设计
红米note4X真机曝光:对比红米Pro,配置性能大升级!
美国的硅谷有大批中国工程师、科学家和技术人员准备回国