您好,欢迎光临本网站![请登录][注册会员]  
文件名称: Java 并发——基石篇.pdf
  所属分类: Java
  开发工具:
  文件大小: 1mb
  下载次数: 0
  上传时间: 2019-07-28
  提 供 者: bani****
 详细说明:Java 并发——基石篇 的 pdf 文档,原文章我发布在知乎上了: https://zhuanlan.zhihu.com/p/75532011 但是知乎的格式不太好看,另外有字数限制,我不得不将文档分为三个部分。 这里提供一份 pdf 格式的文档,格式比较好看,方便大家。导读 声明:本文所有的分析内容基于○ oenDK的java11版本的 Hotspot JVN源代码。 在阅读本文之前,你需要 1.了解Java中的基本的线程使用方式以及注意点 2.了解Java中的基本线程间通讯的方式 3.了解Java中的 volatile的基本语义 4.了解CC++编程 5.了解JN的相关开发知识 6.了解一些86的汇编(仅仅是很简单的内容,要求能读懂) 本文重点分析内容 1.共享内存多核系统基本架构与设计 2.Java内存模型设计 3. Java thread的创建与停止 4. Java synchonized的实现机制 5. Java object的w和 notify/ notify‖实现机制 6. Java volatile关键字的实现方式 阅读建议 1.下载一份Hσ tspot JⅥM∏的代码,了解基本代码架构,并且夲地能够编译和调试,如何编译或 者调试可以参考 OpenJDKνi或者周志明的《深入理解Jαvα虚拟机:第二版》一书 2.使用你熟悉的DE大家J∨M的源码,建议使用 eclipse CDT,其他的E笔者都觉得不是很方 便 3.在阅读的过程中,不能仅仅看本文的分析,需要结合起来,自己下断点或者打印日志调试,并且 不断反复尝试,反复理解核心代码片段 4.最后一点建议,现代J∨M的实现非常复杂,会涉及到很多的操作系统、算法、硬件、统设计以 及性能调优等等方便的知识,所以在阅读源码的时候千万不要深入无关代码的细节部分,否则你 会陷于无边无际的代码海洋而无法自拔~ 本文非常长,笔者写了一个多星期,纯属手打,文中的观点和分析均是本人经过反复的试验和分析得出 的,希望你可以认真读完,我敢保证,只要你认真读完,肯定收获很多,加油 概要 并行是这个时代的主旋律,也是很多现代操作系统需要提供的必备功能。在过去摩尔定律催生下,单个 C門U核心计算的速度越来越快。但是随着产业的发展,单个CPU核心的计算上限已经难以突破,传统 的加强单核的思维模式已经不能满足需求。在古代,人们需要强大的战马驱动战车,为了能够使得战斗 力越来越强,人们驯化出了越来越强劲的战马,但是单匹马的力量始终是有限的,因此人们发明了多马 并驾的战车结构,大量岀现的多乘战车产催生了强大的万乘之国。同样地,在现代计算机领域,人们在 单个C門核心能力有限的情况下,使用多个核心的CPU进行并行计算,以驱动强大的算力。 但是,多CPU和多战马是远远不同的,在现实世界中的计算任务大多需要互相协调,其根本原因是人 类的思维方式就是线性串行的,设计一个完全并行的计算逻辑体系还是有相当大难度的 如何设计—个高并发的程序,不仅仅是工程界的难题,在计算机学术界也是一个需要不断突破的研究领 域。从学术理论提岀,到算法设计,再到工程实施,再到产业验证调优,整个流程都需要比较长的时间 来进行迭代,究其根本,并行计算本身就是非常复杂、不确定的、不可预测的逻辑系统。 多核系统中的一致性 号称一次编写,到处运行的Java,其本身也是构建在不同的系统之上的,以其运行时M来屏蔽系统 底层的差异。因此,在介绍Jaa并发体系之间,有必要简要介绍下计算机系统层面上的并发,以及面 对的问题 我们的目的其实很简单,就是让计算机在同一时刻,能够运行更多的任务。而并行计算,提供了非常不 错的解决方案。虽然这看起来很自然,但实际上面临看众多的问题,其中一个重大的问题就是绝大多数 的计算不仅仅是cPU一个人的事,而是需要很多计算机系统部件共同参与。但是我们知道,计算机系 统中运行速度最快就是C門U,其他部件例如:内存、磁盘、网络等等都是及其缓慢的,同时这些操作在 目前的计算机体系中是很难消除的,因为我们不可能仅仅靠寄存器就完成所有的计算任务。面对高速 CPU和低速存储之间的鸿沟,如果想要实现高效数据通讯,一个良好的解决方案就是在它们之间添加 个 cache层,这个 cache层的速度和整体的速度关系如下 CpU--> cache-->存储 通过 cache这个缓冲地带,实现cPU和存储之间的高效「对话」。这是计算机和软件领域通用的一 个问题解决方案:增加中间层。没有什么问题是一个中间层解决不了的,如果有,那就两层。在运算的 时候,CPU将需要使用到的数据复制到 Cache中,以后每次获取数据都从较为快速的cche中获 取,加快访问速度。 所谓理想很丰面,现实很骨感。这种计算体系有一个重要的问题需要解决,那就是:缓存一致性 cache coherence)问题。在现代的计算机系统中,主要都是多核系统为主。在这些计算机系统 中,每一个CPU都拥有自己独立的高速缓存,但是因为主存只有一个,因此它们之间只能共亨,这种 系统也称为:共享內存多核系统( Shared-Memory multiprocessors System),如下图所示 ProcesSOR Processor Processor Processor One or One or One One or more levels more levels more levels more levels o cache of cache of cache of cache Main memory 1/0 system 因此,当多个处理器同时需要访问同一个内存区域的数据时,首先回去访问cPU的 cache区域中的 数据,但是cαche中的数据也是从共享内存中获取的,此时如果别的門修改了cαche中的数据, 那么就造成了数据不一致的问题了。因此,如果发生了这种「数据竞态」的问题,到底该以哪个数据为 准呢?此时,我们需要一个一致性协议来保证。各个CPU在操作的时候都需要遵守缓存一致性协议来 进行操作,这类型的协议有很多,例如:MS、MES、MoSl、 Synapse、 Firefly以及 Dragon Protoco等等。所以,通常情况下,共享内存多核系统的架构如下所示 CPU Cache 缓存 cace下性协上 主存 CP Cache 除了使用高速 cache来缓和cP∪和存储设备之间的速度鸿沟,为了能够充分利用多核CPU的处理性 能,处理在实际执行机器指令时并不一定会按照程序设定的指令顺序执行,可能存在代码乱序执行 (○ut○f- Order execution)优化。注意,这里虽然乱序执行了,但是系统会保证执行的结果逻辑上 的正确的,从宏观上看就好像是顺序执行一样。举个例子,比如我们有如下代码 int a valuel int b value2 这两句话实际的执行顺序可能是先赋值a然后赋值b,但是也可能反过来,反正这两句话执行完毕之后 α和b的值都被赋值上了就可以,这里对外表现为顺序串行执行,这其实就是 as-serIo协议保证的。 为什么需要这样?一方面这两句话本身并没有什么逻辑上的依赖性,完全可以并行执行;另一方面,如 果我们傻傻地按照顺序执行的话,在执行第一句话的时候,我们可能需要从主存中读取Vo|e1的值, 这种操作对于CPU来讲是及其缓慢的操作,如果我们顺序执行的话,那么就只能等待voue值读取 成功之后才能继续执行下面的指令,这样就造成了CPU的空等待,白白浪费了资源。 JA∨A内存模型 上面我们探讨了共享内存多核系统的内存模型,我们提到了高速缓存以及缓存一致性问题,同时还介绍 了指令乱序执行的问题。其实,这些概念在Java中也是存在的。因为 Java的目标是:一次编写,到 处运行。每一个计算机系统或者操作系统都会有自己特殊的内存模型,如果Java想要实现一次编写到 处运行的目标,就必须在JM层面上将系统之间的差异屏蔽掉。面对如此多的系统,最好的方式就是 定义一套Javo自己的内存访问模型,然后在不同的硬件平台和操作系统上分别利用本地接口来实现。 这里的思想其实和增加cαche是一样的,通过增加中间层来解决系统差异带来的协作问题。 Java在1.5版本中引入了JSR133标准,这个标准提出了Java中的并发内存模型和线程规范,这个 标准的发布标志着Java拥有独立于系统平台的并发內存模型。和C/C++不同的是,Java并没有直接 操作系统平台中的内存模型,而是自己定义了一套机制,这套机制包含了并发访问机制、缓存一致性协 议以及指令重排序解决方案等内容。在JSR133标准中,定义了如下的Jova并发内存模型 Thread 工作内存 Thread 工作内存 Save和 oac 主存 Threar 工作内存> 可以看到,这里的内存模型和上面讲到的计算机系统中的内存模型是十分类似的。在JVM中,并发的 最小单位是 Thread,在不考虑JⅥM线程实现细节上,可以简单认为一个 Thread对应一个内核线程, 这样就可以进而认为 Thread对应一个CPU核心。这里需要注意的是,工作内存和JαVo内存区域中 的堆、栈或者方法区(avo和nave)等并不是一个层面上的东西,它们之间也没有直接的对应关 系。同时,很多人会误以为这里的工作内存其实就是TLAB( thread local allocation buffers),字面 上看起来很像,但是没有任何关系的 从上面的图中,可以看出每个线程的工作内存和主存之间的一致性保证是通过saVe和oad等等一系 列的操作完成的。JSR133早期版本中定义了8种操作,但是后来处于描述简化以及方便不同JVM实 现修为了4种操作,但是只是描述上的修改,内存模型基本设计并没有改变(周志明的书中有描述,感 谢这本书的指点)。这里我们采用最新版本的4种操作来描述,这种方式比较清晰易懂。这4种操作和 Java内存模型的对应关系如下图 Thread Thread Working Memory Working Memory CopY valid?>Y- Copy unik Main Memory Main Memory 下面分别介绍下上面图中涉及的4种操作 1.read: Java执行引擎访问本地工作內存中的变量副本,如果变量副本无效(变量副本不存在也 是无效的一种),那就去主存中获取,同时在本地工作内存中缓存一份 2. write:Java执行引擎将最新的变里值赋值给工作內存中的变量副本,同时需要判断是否需要将 这个新的值立即同步给主内存,如果需要同步的话,还需要配合ock操作 3.lock:Java执行引擎将主内存中的变量锁定,锁定旳含乂有:其他的线程在此之后不能访问这 个变量直到本线程 unlock;一旦锁定,其他线程针对这个变量的操作必须等待 uno∝k:Java执行引擎将主內存中的变量解锁,解锁之后才能:各个线程并发访问这个变量; 某个线程再次锁定 JA∨ A THREAD创建 在Java中,我们都知道,一个线程直接对应了一个 Thread类对象。创建和启动一个线程是比较容易 的,我们只需要创建一个 Thread对象,然后调用对象的sar方法即可。但是在创建一个 Thread对 象和启动线程JM中究竟发生了什么?本节我们就来看下。 如果你仔细看过 Thread类的源码就知道,在创建一个 Thread对象的时候,除了一些初始化设置之外 就没有什么实质性的操作,真正的工作其实是在sto叶方法调用中产生的。也就是说,只是创建了一个 Thread对象和创建一个普通的Java对象没什么实质性的差异。因此我们需要看下在 Hotspot11中的 Thread star实现,那么怎么找实现的代码呢?打开 Thread类的代码,在这个类开始的地方我们看到 了如下的代码 / Make sure registerNatives is the first thing does. * private static native void registerNatives()i static registerNativesoi 如果你熟悉JN的话,就知道这里的 registerNatives方法就是将 Thread类中的」avo方法和一个本地 的C/C+函数进行对应,同时由于这个方法是类加载的时候调用的,因此在类首次加载的时候 Bootstrap类加载)就会注册这些 native方法,那么 Thread中都有哪些 native方法呢?看下 Thread类的结尾处(JDK源码中一般都是将 native方法声明在类的结尾处,方便查找) public static native Thread currentThread()i public static native void yield(i public static native void sleep(long millis)throws InterruptedException; private native void start()i private native boolean isInterrupted(boolean ClearInterrupted)i public final native boolean isAlive()i public native int countstackFrames() public static native boolean holdsLock(Object obj)i private static native stackTraceElement[l[] dumpThreads(Thread[ l threads) private static native Thread[] getThreads(); private native void setPriorityo(int newPriority)i private native void stop(object o) private native void suspendoo; private native void resume() private native void interrupt() private native void setNativeName(string name); 这些方法,不用说你肯定非常熟悉,这里就不赘述了。
(系统自动生成,下载前可以参看下载内容)

下载文件列表

相关说明

  • 本站资源为会员上传分享交流与学习,如有侵犯您的权益,请联系我们删除.
  • 本站是交换下载平台,提供交流渠道,下载内容来自于网络,除下载问题外,其它问题请自行百度
  • 本站已设置防盗链,请勿用迅雷、QQ旋风等多线程下载软件下载资源,下载后用WinRAR最新版进行解压.
  • 如果您发现内容无法下载,请稍后再次尝试;或者到消费记录里找到下载记录反馈给我们.
  • 下载后发现下载的内容跟说明不相乎,请到消费记录里找到下载记录反馈给我们,经确认后退回积分.
  • 如下载前有疑问,可以通过点击"提供者"的名字,查看对方的联系方式,联系对方咨询.
 输入关键字,在本站1000多万海量源码库中尽情搜索: