并发指一个处理器同时处理多个任务,但这个定义只是从宏观上来讲的。举个生活中的例子来说明,一个电商小二同时接待两个客户,小二通常的做法是在和A客户聊的间隙回复B客户的问题,和B客户聊的间隙又回复A客户的问题,这样看起来小二同时服务了A和B,但是具体到某次答复,小二只是在为一个客户服务。那么对应到计算机上,并发是怎样发生的呢?

计算机的CPU通过给每个线程分配时间片来实现并发。时间片是CPU分配给各个线程的时间,每个线程被分配一个时间段,该线程在这个时间段拥有CPU的执行权,这个时间段就成为时间片。如果在时间片结束时线程还在运行,则CPU将被剥夺并分配给另一个线程。如果线程在时间片结束前阻塞或结束,则CPU当即进行切换,而不会造成CPU资源的浪费。这样,宏观上看有多个线程在并行进行;但是从微观上看,由于只有一个CPU,一次只能处理一个线程线的一小段指令。

说到这里,似乎忽略了一个问题,为什么要引进并发呢?仍以上面的电商小二为例,在串行模式下小二先服务客户A,等对客户A的服务完成之后再对客户B进行服务,这样小二和客户沟通中的时间空隙时间就白白流失掉了,串行模式的效率低于并发模式。另外并发模型更能满足复杂业务的需要,因为并发模型能更好的模拟现实中的问题 。所以引进并发是很有必要的 。

接下来了解一些计算机的知识,为后面学习Java并发做铺垫。

1. 高速缓存

计算机执行的任务大体上分为在CPU上计算和在内存上存取数据两部分。然而计算机执行任务依赖的两个硬件、CPU和内存在性能上差距有几个数量级之大,而且短时间内内存性能的不足是弥补不了,于是工程师采用优化运行流程来解决问题。工程师在计算机系统加入一层的高速缓存(读写速度几乎接近CPU的运算速度)来作为内存与CPU之间的缓冲。这样可以将计算使用的数据复制到缓存中,CPU运行时直接操作缓存中的数据,当运算结束后再将数据从缓存同步回内存之中,这样避免了CPU在运行的过程中长时间停止来等待从内存中读写数据了。

高速缓存弥补了CPU的执行速度和内存存取速度差距,但是也造成了新的问题:缓存一致性问题。在多核CPU系统中,每个核都有自己的高速缓存,同时这多个核共用一个主内存。这样就可能发生一种情况:一个以上的CPU缓存了同一个主内存上的某个数据,CPU各自独立的操作自己缓存的数据,结果主内存的某个数据在不同的CPU中的缓存值却是不一样的。

既然高速缓存方案已经广泛使用了,缓存一致性问题也一定得到了解决。这个解决方案是要求处理器在访问缓存时遵循特定的协议,这类型的协议有很多,如MESI协议:当CPU写数据时,如果发现操作的变量是共享变量,即在其他CPU缓存中也存在该变量的副本,会发出信号通知它们将该变量的缓存行置为无效状态,当其他CPU需要读取这个变量时,发现自己缓存的该变量的副本是无效的,它就会从内存重新读取。

仔细看MESI协议的原理,好像最终也没能让缓存保持一致,而是让CPU及时发现缓存的不一致,并且让不一致的缓存失效,有点儿兜底方案的感觉。

2. CPU的工作模式

一条计算机指令的执行一般可以可以分为以下几个步骤:

取指 IF

译码和取寄存器操作数 ID

执行或者有效地址计算 EX

存储器访问 MEM

写回 WB

这些步骤执行的过程中用到的是不同的硬件,比如,取指用到的是PC寄存器和存储器,译码时用到的是指令寄存器组,执行时会使用ALU(算数逻辑单元)。基于这一特点,工程师发明了流水线技术来执行指令。这样指令的执行顺序将不再是串行的,不会因为一条指令卡在某个阶段而影响后面指令的执行,只要CPU内部相应的处理部件未被占满就可以不停的执行指令,这样CPU的使用效率就会非常高。

但是,这也会带来一个问题,后面执行的指令可能会比在它之前执行的指令完成的早,从而造成一种乱序,因为某些指令在EX阶段耗时比较长的现象常有发生。这就是所谓的"顺序流入,乱序流出"。

另外,现代处理器引入了写缓存优化。处理器使用写缓冲区临时保存向内存写入的数据,而不是直接将数据写入内存,然后采用批处理的方式刷新写缓冲区将数据批量写入内存,而且会合并写缓冲区中对同一内存地址的多次写。这样既可以可以保证指令流水线持续运行,同时也减少对内存总线的占用。

现在我们看另一种情况,有A、B、C、D四条依次执行的指令,其中B指令的执行需要依赖A的计算结果,这时候B指令就要停顿在某个阶段,等待A执行完成后才能执行,C和D正常执行。想一想有没有办法缩短B指令执行过程中的停顿时间?肯定是有的,因为B和CD之间没有关联,可以把B放在C和D之后执行,这样等B开始执行的时候说不定A已经执行完成了,CPU不需要停顿,这样CPU的使用效率又有所提高。

事实上,现在很多语言也是这么做的,在编译阶段保证上下文前提的下会对指令进行重排,以提高CPU的处理性能。

3. 原子操作的实现原理

原子本意是"不能被进一步分割的最小粒子",而原子操作意为"不可被中断的一个或一系列操作"。在多处理器上实现原子操作有点儿复杂,下面看下Intel处理器是如何实现原子操作。

对于基本的内存操作的原子性处理器会自动保证,否则并发的概念就将不复存在了。处理器保证从内存中读取或者写入一个字节是原子的,意思是当一个处理器读取一个字节时,其他处理器不能访问这个字节的内存地址。但是复杂内存操作的原子性需要借助总线锁定和缓存锁定两个机制来保证。

3.1 使用总线锁保证复杂操作原子性

所谓总线锁就是使用处理器提供的一个LOCK#信号,当一个处理器在总线上输出此信号时,其他处理器的请求将被阻塞,那么该处理器就可以独占共享内存(听到锁是不是很亲切,很熟悉)。感觉和处理器自动保证基本内存操作原子性的原理差不多,都是排斥其他处理器同时操作,只不过前者独占的是某个字节的内存地址,而总线锁独占的是整个内存。

独占整个内存听着就很浪费,没有代价小点儿的方法吗?当然有,缓存锁定锁定机制就是。

3.2 使用缓存锁定来保证原子性

在上面高速缓存的知识里面,我们知道每个处理器都有一套高速缓存用于缓存频繁操作的内存,处理器不直接操作主内存的地址,而是操作这些缓存,操作完成之后再将缓存数据写回主内存。在这种模式下,只要保证缓存写回的准确就可以保证该操作的原子性。这也就是缓存锁定保证复杂操作的原子性的原理。下面是规范的描述:

内存区域如果被缓存在处理的缓存行中,并且在Lock操作期间被锁定,那么当它执行锁操作回写到内存时,处理器不在总线上声言LOCK#信号,而是修改内部的内存地址,并允许它的缓存一致性机制来保证操作的原子性,因为缓存一致性机制会阻止同时修改由两个以上处理器缓存的内存区域数据,当其他处理器回写已经被锁定的缓存行数据时,会使自己的缓存行无效。

现又有一个问题了,既然有低损耗缓存锁定机制,为什么还要用总线锁定机制?这是因为有以下两种情况不能使用缓存锁定:

第一种情况是:当操作的数据不能被缓存在处理器内部,或者操作的数据跨越了多个缓存行时。

第二种情况是:有些处理器不支持缓存锁定,比如Intel 486 和Pentium 处理器。

上面这些计算机硬件知识都是和并发相关的,因为Java程序也是在计算机上运行的,那么Java并发应该也是基于计算机的并发特点做的设计,了解了这些知识,后面可以比较容易的理解Java并发的知识。

参考文献 《Java并发编程的艺术》

java学生背景知识要求,好好学习Java并发 一、背景知识相关推荐

  1. 数据结构java学生成绩排序_数据结构学习--Java简单排序

    冒泡排序需要元素每次遍历都从最底部向上冒泡,找到适合的位置后,该位置之后的元素继续向上冒,这样一趟排序结束后,将冒出最大或者最小值. 选择排序需要元素从0号位开始向上遍历一遍,并将最小值放到0号位上, ...

  2. Java就业方向有哪些?学习Java开发能做什么?

    学习Java开发都能做什么?Java主要应用在B/S和C/S领域.由于科技的不断发展,B/S将不足以满足社会需求,C/S将会是社会发展趋势.随着Servlet技术的使用,Java向Web移动设备方向挺 ...

  3. java实现第四届蓝桥杯好好学习

    好好学习 汤姆跟爷爷来中国旅游.一天,他帮助中国的小朋友贴标语.他负责贴的标语是分别写在四块红纸上的四个大字:"好.好.学.习".但是汤姆不认识汉字,他就想胡乱地贴成一行. 请你替 ...

  4. 什么?你还在花一两万学Java,快来看看小白学习java全路线吧

    ---------------------------龙珠悟空------------------------- 龙珠悟空一个写故事的程序员,小白学java专栏我会以故事的方式,通过老师讲解同学讨论个 ...

  5. 学java专科_专科学历可以学习java开发吗

    学习Java的热潮越来越高涨,除了转行而来的人,很多刚毕业的学生也加入到其中.很多人都觉得学习Java需要有一个高学历作为基础,一些专科生在学习之前会犹豫,他们是否能学习Java,首先学程序开发,入行 ...

  6. 33岁适合学java吗_33岁女生想学习Java好不好

    33岁的女生总是希望自己能够掌握一技之长,但是在专业技术这些道路上,可能大多数的女生要结合自己的现有情况来看,目前来说在互联网领域技术里面,Java这项技术确实也是非常不错的.不过不知道从什么时候开始 ...

  7. 大学学了java可以做点什么_学习Java的,大学毕业一般从事些什么工作?

    展开全部 我这是拷贝的,62616964757a686964616fe59b9ee7ad9431333332643361不过也就差不多了,说实话,java的东西太多了.还是要到工作的时候慢慢用的,学好 ...

  8. java基础知识点_零基础学习Java语言,各个阶段需要掌握的知识点

    随社会的脚步的不断发展,Java技术在不断的与时俱进,这也是Java一直长盛不衰的原因之一.Java技术的学习,永远没有早晚之分,技不压身,对于21世纪的我们80后,90后,甚至00后,尤其适用! 那 ...

  9. java环境怎样搭建_如何学习JAVA?怎么搭建JAVA环境?怎么安装JDK?

    JAVA 在学习JAVA前,我们必须了解并搭建好JAVA所需的开发环境,要让你写代码能让机器听得懂并执行,JDK(Java Developers Kits)自然是是必须的 安装JDK前的准备 首先我们 ...

最新文章

  1. ES6-Promise对象
  2. 网工必备的存储知识详解
  3. 每次重启需要source /etc/profile的原因-环境变量
  4. 亦云小组KTV点歌系统简介
  5. 无限极 php算法,无限极分类算法,对你一定有帮助
  6. dispose方法的使用
  7. Sql Plus 操作
  8. matlab中ezplot和plot, fplot这3
  9. 用户购买预测使用paddlerec的baseline
  10. 封装,继承,多态的理解
  11. 6款主流PDF编辑器测试,快来看看哪一款最适合你吧
  12. Linux怎么复制文件到其他文件夹
  13. Unity3d官网链接失效
  14. Java Reflection
  15. 关于爱情——苏格拉底如是说 (转)
  16. ViewPager标签栏滑条
  17. html基本标签斜体,请选择产生斜体字的HTML标签:
  18. “值得”关注公司:我们应该向优衣库学习什么?
  19. git检出新分支遇到的文件路径过长Filename too long的问题
  20. HDU1000题纪念

热门文章

  1. ABAP常用字符串操作收集整理
  2. 花小猪,真正的对手是谁?
  3. 大健康产业里的巨头身影:格局已定但业务创新才刚刚开始
  4. vc6怎么看错误在哪_网红莉哥怎么红的为什么被封了 网红莉哥1400事件视频在哪看...
  5. php验证码切换不刷新页面,Yii2解决验证码点击、刷新页面不刷新问题
  6. fastjson反序列化漏洞_漏洞预警Fastjson再爆反序列化代码执行漏洞;星巴克被发现存在信息泄露风险...
  7. android+note2+分辨率,魅蓝Note2的屏幕尺寸是多少?魅蓝Note2的分辨率是多少?
  8. Python基础教程:类的特殊成员及高级特性
  9. Python实现字符串反转的6种方法
  10. urllib库添加headers的一般方法