java高并发一

一,CPU的多核并发架构与JMM模型

1.1什么是CPU的多核并发架构?

现在的电脑的CPU一般是多核的(说白了就是将两个以前的多个CPU整合到一起)如下图所示:由于CPU读取寄存器和CPU读取内存(又称主存)的速度差异巨大(相差几百倍,上千倍),所以引入缓存来缓存它们速度差异大的问题(由此来提高计算机运行的速度),由此组成的CPU——》缓存——》主存的架构如下图所示为CPU的多核并发架构。

1.2为什么加入缓存就可以提高计算机的运行速度,它是如何解决CPU与内存速度不匹配问题的?

根据空间一致性原则,时间一致性原则我们知道:内存中的某处数据A被读取到CPU中,那么A及其附件的数据大概率也会被读到CPU中。如果数据A在此刻被CPU读取,那么A在不久的将来也很可能被CPU读取。例如:我们在程序中的一个数组,如果这个数据的某个数据被使用到,那么它的相邻数据很可能被使用到,并且该元素所在的数组在不久的将来很可能被再次使用。如果CPU从内存读出一个数组元素来使用,使用后在存入内存,那么大部分的时间都会用在读取上,CPU将会被闲置。此时如果我们把整个数组读到一个高速缓存上,那么每次读取数据就不需要去内存中拿了,直接在缓存中拿,那么用于数据读取的时间就减少了,由此CPU的利用率提高了,计算机的运行速度自然就快了。

1.3为什么不直接把数组直接读到CPU中的寄存器呢?

因为CPU中寄存器的存储空间十分小,并且造价昂贵。CPU的价格>缓存>内存>硬盘,CPU的存储空间<缓存<内存<硬盘 

1.4为什么要学习CPU的多核并发架构,它与高并发有什么关系吗?

因为计算机后期的发展,我们使用了三级缓存来提高计算机的速度,三级缓存中的测试会导致正在并发中的代码数据不一致的问题,所以在学习高并发之前需要知道如何解决这个问题。

1.5什么是三级缓存,为什么要将缓存分三级?

CPU——》一级缓存——》二级环境——》三级缓存——》内存

 为了提高计算机的速度,原理和1.2的差不多

让你们看一下我的三级缓存的大小如图所示:

 

 1.6 能否说一下?三级缓存是如何导致并发过程中数据不一致的?

 我们知道:一级缓存是二级缓存的子集,存的是二级缓存中经常被用到的那一部分数据(以此类推二级缓存与三级缓存,三级缓存与主存的关系)由于一级缓存和CPU的内核一样多,当CPU1号读取数据A到它的一级缓存时,CPU2号也读取到它的一级缓存,CPU1号对数据A修改,修改数据A=A+1同步回内存,此时CPU2号不知道A数据被修改,它也进行A=A+1的操作,将数据同步的到内存中,这时会对原有的数据A+1进行覆盖,最终的值为A+1(预期的值应该是A+2)。那么这就是最终答案吗?当然不是。java虚拟机为了提高并发的效率,参考的就是CPU的三级缓存模型,于是就建立了JMM(java内存模型)JMM内存模型存在以上并发的问题,导致了我们java查询再并发时出现问题

 1.7java内存模型

我们知道jvm的存储空间主要是堆和栈,其中堆存储的对象实体,栈内存存储的引用之类的。下面是JMM的大致结构,其中堆栈对应内存(或者二级,三级缓存),工作内存对应一级缓存设计,java线程对应CPU。所以说JMM是仿造CPU多核并发结构进行设计。

注意:理解成一个线程运行时,对应一个CPU运行它。有的人把堆栈存储器写成内存(我觉得jvm它是一个软件运行在操作系统上的东西,应该和操作系统中的概念做一些区分)

堆栈存储区(其实就对应的内存)

1.8JMM通过什么来解决数据不一致的问题?

以下是它调用存储系统执行的原子操作(不可被中断的操作)

      read操作:将数据从堆栈中读出来到一个缓冲区A

      load操作:将缓冲区A的数据写入到工作内存

      use操作:线程读取工作内存的数据进行计算

-------------------以上是读取数据到线程的原子操作

      assign操作:线程在CPU中执行,将计算好的值存储到工作内存中

      store操作:将工作内存大数据写入缓冲区B

      write操作:将缓冲区B的数据写入原有的为止,对其进行赋值操作

--------------------以上是将修改后的数据存储回堆栈的原子操作

      lock操作:将堆栈中的变量加锁,标识为内存独占状态

      unlock操作:堆栈中的变量解锁,其它线程就可以锁定该变量

--------------------以上是为了实现资源的互斥的操作(此资源在某一时段内只允许一个线程使用)

java保证数据的一致性:在代码层面添加对需要保证数据一致性的变量A编写加上volatile关键字实现的,执行A的赋值时,jvm识别到volatile关键字,就会多跑一句汇编语言如下所示:

它的作用是会让jvm马上将修改后的变量A后,对堆栈中的A进行lock(或者多个CPU中的线程同时进行write操作),将其立即写回到堆栈中(如果没有执行此编译语言,是不会立即将数据A协会堆栈的,堆栈的本质就是内存),进行unlock操作,此时数据A的写回内存的操作经过总线时,会触发其它CPU的缓存一致性协议机制(宣布缓存中的数据A的副本无效,缓存此时泛指工作内存),也会触发其它CPU的嗅探机制(查询数据A是否宣布无效,如果是,同步数据)

1.9并发编程的三大特性是什么?

可见性:多个CPU中一级缓存(工作内存)中数据的一致性(它们之间相互可见)

原子性:就拿a++操作来说,分为三个步骤:读取a的值,a的值加一,将a+1的值写回堆栈。原子性就是这三个步骤为一个原子,要么都执行,要么都不执行(撤销已执行)。

有序性:代码在运行期间保证按照编写的顺序进行执行的(由于CPU多核并发架构,为了提高计算机运行效率,可能导致后写的代码先执行,所以才需要保证有序)

我们通过volatile关键字保证代码有序性,可见性;synchronize保证代码操作原子性

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值