做ppt图片用的网站有哪些问题,wordpress中国分享插件,小程序源码库,什么网站可以做调察问卷我们从操作系统的发展讲起#xff0c;为什么要有线程这个概念出现。《Java多线程学习笔记(一) 初遇篇》讲Java平台下的线程#xff0c;如何使用和创建#xff0c;以及引入线程后所面临的问题#xff0c;为了解决线程安全问题#xff0c;Java引入的机制#xff0c;这也是《…我们从操作系统的发展讲起为什么要有线程这个概念出现。《Java多线程学习笔记(一) 初遇篇》讲Java平台下的线程如何使用和创建以及引入线程后所面临的问题为了解决线程安全问题Java引入的机制这也是《Java多线程学习笔记(二) 相识篇》讨论的问题,《Java多线程学习笔记(三) 甚欢篇》是讲线程协作即如何让线程之间协作去处理任务《Java多线程学习笔记(五) 长乐无极篇》讲了CompletableFuture这个强大的异步编排组件《Java多线程学习笔记(六) 长乐未央篇》 讲ForkJoin模式《Java多线程编程范式(一) 协作范式》 讲使用Java提供并发核心库来解决一些问题。但是在《Java多线程学习笔记(一) 初遇篇》我们的讨论相对还比较粗糙当时我的想法是先基本搭建一个模型来快速的熟悉Java的并发编程在实践中先用起来我们没有直接讨论线程安全什么是线程安全这个问题在当时的我去看没有找到一个很完美的定义还有并发模型并发是难以验证的那我们该如何验证我们将统一收拢统一回答这些问题。
从指令集架构谈起 单看指令集架构来说这是一个有些相对陌生的名词让我们从生活中稍微常见的事物讲起也就是苹果电脑Mac很多程序员都喜欢MacMac中现在比较热的一款是Mac m1、m2了喜欢苹果的人对m1和m2相当喜欢这里说的m1和m2也就是CPU的代称这两款CPU的指令集架构是ARM那什么是指令集架构 在回答这个问题的时候我们还是要请出《程序是如何运行的(一)》这篇文章的图:
图片九.png
从这幅图我们可以看到指令集架构是硬件系统和软件的桥梁连接了硬件和软件。那他是什么呢?
An Instruction Set Architecture (ISA) is part of the abstract model of a computer that defines how the CPU is controlled by the software. The ISA acts as an interface between the hardware and the software, specifying both what the processor is capable of doing as well as how it gets done.
指令集架构是计算机抽象模型的一部分定义了CPU如何被软件控制。指令集充当硬件和软件之间的接合点规定了处理器能够做什么以及如何完成。
The ISA provides the only way through which a user is able to interact with the hardware. It can be viewed as a programmer’s manual because it’s the portion of the machine that’s visible to the assembly language programmer, the compiler writer, and the application programmer.
指令集是用户和计算机之间进行交互的唯一途径。它可以被看做是程序员的手册因为它是程序员(汇编语言程序员编译器开发者、应用程序程序员) 可以看到的机器部分。
The ISA defines the supported data types, the registers, how the hardware manages main memory, key features (such as virtual memory), which instructions a microprocessor can execute, and the input/output model of multiple ISA implementations. The ISA can be extended by adding instructions or other capabilities, or by adding support for larger addresses and data values.
指令集架构定义了数据类型、寄存器、硬件如何管理主存关键特性(如虚拟内存)微处理器可以执行哪些指令输入输出模型。指令集架构可以通过增加指令、其他功能、增加对更大地址和数据值的支持来进行扩展。
–ARM官网
这里提到了数据类型我想起学Java的时候老师谈到数据类型的时候说你家附近开了一家水果店卖西瓜几乎不要钱大家都拿东西去买有的人拿大袋子有的人拿小袋子你会拿什么去装因为我非常爱吃西瓜所以我说的是我会开辆车去装几乎不要钱嘛。其实老师讲这个例子只是想引出数据类型是数据的容器。我又想起小的时候吃饭饭量小的用小碗饭量大的用大碗。
那设计一个编译器来说一般的思路就是先引入对应的数据类型那数据类型看来还是来自于指令集架构的支持已知Java是跨平台的这个平台我们可以理解为指令集架构从Github上OpenJDK的源码可以看出
iKCHLN.jpeg
那么Java一共支持了七种指令集架构aarch64、arm、ppc、riscv、s390、x86、zero。 这里简单的介绍一下指令系统随着技术的进步计算机的形态产生了巨大的变化从巨型机到小型机到个人电脑再到智能手机其基础元件从电子管到晶体管再到超大规模的集成电路。虽然计算机的形态和应用组合千变万化但从用户感知的应用软件到最底层的物理载体计算机系统均呈现出层次的结构。下图展示了这些层次:
iKCqmV.jpeg
从上到下计算机系统可分为四个层次分别为应用软件、基础软件、硬件电路和物理载体。软件以指令形式运行在CPU硬件上而指令系统介于软件和硬件之间是软硬件交互的接口(这里引用的是《计算机体系结构基础》原文用的是界面我想是用错了词应当理解为接口更为得体)有着非常关键的作用。软硬件本身更迭速度很快而指令系统则可以保持很长时间的稳定。有了稳定不变的指令系统接口软件与硬件得到有效的隔离并行发展。遵循同一指令系统的硬件可以运行为该指令系统设计的各种软件比如X86计算机既可以运行最新软件也可以运行30年前的软件(这一句话也引用自《计算机体系结构基础》但是我的理解倒是与此不一致X86计算机可以运行30年前的软件得益于两方面一方面是指令系统的向前兼容另一部分则源于操作系统的向前兼容)。依据指令长度的不同指令系统可分为复杂指令系统(Complex Instruction Set Computer简称为CISC) 精简指令系统(Reduced Instruction Set Computer, 简称RISC) 和 超长指令字(Very Long Instruction Word, 简称VLIW) 指令集三种。早期的CPU都采用CISC结构这与当时的时代特点有关早期的处理设备昂贵且处理速度缓慢设计者不得不加入越来越多的复杂指令来提高执行效率部分复杂指令甚至可与高级语言中的操作直接对应。这种设计简化了软件和编译器的设计但也显著提高了硬件的复杂性。
随着硬件的发展CISC结构出现了一系列问题。大量复杂指令在实际中很少用到典型程序所使用的的百分之八十指令只占到指令集总指数的百分之二十消耗大量精力的复杂涉及只有很少的回报。针对CISC结构的缺点RISC遵循简化的核心思路RISC简化了指令功能。上面的ARM 指令集架构就是RISC架构ARMv8-A引入了64位架构我们称之为Aarch64在目前来看它们都指同一事物也就是公版64位ARMv8以后的所有64位ARM架构。那X86是RISC还是CISC以前我认为是CISC架构但是我在《计算机体系结构基础》中看到这么一句话:
X86处理器中将CISC指令译码为类RISC的内部操作然后对这些内部操作使用诸如超流水、乱序执行多发射等高效实现手段。 所以X86指令集架构这么一看也不能完全算作CISC架构CISC和RISC有点走向融合的感觉。PPC 是Power PC的缩写基于RISC。RISC-V从名字就可以看出基于RISC。S390没查到资料Zero没有指令系统(没有指令系统引自维基百科对这个我也缺乏认知)资料太少不知道是怎么运作的。
那么不同的指令集支持的指令就是不同的而JVM是一个跨平台的虚拟机Java是一个跨平台的语言也就意味着Java要保证在适配的平台上行为一致。
CPU 内存模型 浅谈模型 CPU这个词我们认识内存这个词我们也认识那模型呢当我们说起模型这个词的时候我们到底在说什么 当我说起模型这个词的时候我想到的是预测我想起的是预测抽象出运行规律根据运行规律来进行预测这让我想起高中生物教材的K值曲线:
[iLo1Uy.jpeg]
这事实上是一种数学模型那什么是数学模型 一般地说数学模型可以描述为对于现实世界的特定对象为了一个特定目的根据特有的内在规律作出一些必要的简化建设运用适当的数学工具得到的一个数学结构。其实结构这个词如果对我文章有些熟悉的话其实这个词已经讨论过很多遍了, 这里再讨论一下:
the arrangement of and relations between the parts or elements of something complex.
复杂事物的各个部分或要素之间的安排和联系。
上面的种群增长数学模型描述的就是在资源和空间有限天敌的制约等(即存在环境阻力)的情况下时间与种群数量之间的关系。数学模型最终是为了得到一个关系那内存模型呢 数学模型和内存模型都是模型那该怎么理解模型这个词呢
模型是指对于某个实际问题或客观事物、规律进行抽象后的一种形式化表达方式。 那么CPU内存模型就是对某个实际的读写问题进行抽象后的一种形式化表达方式那究竟是遇到了怎样的问题呢? 让我们从冯诺依曼计算机模型讲起冯诺依曼计算机模型是一种将程序指令存储器和数据存储器并在一起的计算机设计概念结构。根据冯诺依曼结构设计出来的计算机我们称作冯诺依曼计算机又称存储程序计算机。计算机在运行指令的时候会从存储器中一条条将指令取出通过译码(控制器)从存储器中取出数据然后进行指定的运算和逻辑等操作然后再按地址把运算结果返回内存中取。接下来再取出下一条指令在控制器模块中按照规定查找。依次进行下去。直至遇到停止指令。程序与数据一样存储按照程序编排的顺序一步一步地取出指令按规定操作自动地完成指令规定的操作是计算机最基本的工作模型。下面这张图是Intel系统的硬件结构:
img
一般我们看CPU的性能一般都是看主频主频也被称之为时钟速度那什么是时钟速度:
CPU 每秒要处理来自不同程序的众多指令如算术等低级计算。时钟速度则测量 CPU 每秒执行的周期数以 GHz千兆赫为单位。从技术上讲“周期”是由内部振荡器同步的脉冲但就我们的目的而言它们是帮助理解 CPU 速度的基本单位。在每个周期中处理器内数十亿个晶体管会打开和关闭。 时钟速度为 3.2 GHz 的 CPU 每秒执行 32 亿个周期。较早的 CPU 的速度以兆赫计算或每秒几百万个周期。有时多个指令可在一个时钟周期内完成而在其他情况下一条指令可能需要多个时钟周期来处理。由于不同的 CPU 设计处理指令的方式不同所以最好比较同一品牌和同一代 CPU 的时钟速度。
例如5 年前时钟速度更高的 CPU其性能可能还不如时钟速度更低的新 CPU因为新架构可以更高效地处理指令。英特尔® X 系列处理器的性能可能优于时钟速度更高的 K 系列处理器因为它可以在更多的内核之间分配任务并具有更大的 CPU 缓存。但是在同一代 CPU 中在许多应用方面时钟速度较高的处理器通常优于时钟速度较低的处理器。因此请务必对同一品牌和同一代系的处理器进行比较。
—Intel官网, 参看参考文档[13]
频率对比
我这里来补充介绍一下时钟周期是计算机中最基本的、最小的时间单位在一个时钟周期内CPU仅完成一个最基本的操作。我笔记本的CPU主频为2.3GHZ那么一秒之内我的CPU就可以执行23亿基本操作。按照一般的推理来说提高CPU的运算性能我们在提升架构性能的同时提升主频就可以了也就是一边研究更高效的处理指令一边研究怎么在高效的架构更加快速的提升时钟速度。但是遗憾的是我们并不能主频不能无限制的被提升, 原因在于主频提高过了一个拐点之后功耗会爆炸增长提高主频这条路走不通那就再加一个处理器这也就是多核处理器。
多核处理器和并发任务的出现 引入了多核处理器之后可以继续提升CPU的性能了但是又引入了新的问题这没办法在计算机世界里面没有银弹能够应付一切情况。在多核CPU情况下计算机的内存结构可以被下图表示:
iLLr1A.jpeg
数据从主内存一级一级的加载到CPU完成指令之后再将计算结果写入对应的内存地址其实这里还漏了磁盘我们姑且忽略。早期的计算机是独占式的
图片一.png
像上面的图片一样一个程序写好了放在纸带上被读取执行但是随着硬件的高度集成化发展计算机变得可以同时执行多个进程这某种程度是一种并发比如我现在写文章用typora写一边用浏览器打开b站听歌曲浏览器和typora事实上是两个进程但给我的感觉就是计算机同时在接收我敲击键盘的指令一边在驱动我的音响播放音乐这一切都源于CPU强大的计算速度这对于用户来说是无感知的想起我之前写的文章《当我们说起多线程与高并发时》:
计算机用户通常认为操作系统能够同时做很多事情是无比正常的事情因为他们通常会在使用办公软件处理文字的时候其他程序在下载文件管理打印处理音频。甚至是一个应用程序也是希望同时能够做不止一件事。例如一个音频处理程序必须同时从网络上读取音频然后解压缩管理播放更新进度(这是现在很稀松平常的事情也就是在线听歌)。不管是文字处理软件有多忙它也总是在时刻响应键盘和鼠标。能够同时做不止一件事情的软件我们称之为并发软件。
上面的并发强调的是同时做不止一件事情这是一种操作系统提供给程序的假象事实上他们可能是交替执行的(并发)当然也可能是同时执行的(并行)这取决于当前计算机系统的基本配置和忙碌程度有关。假设当前计算机不是很忙碌也就是说运行的程序并不多,又假设CPU很强大,进程的两个动作(现代操作系统来说一般是线程现代操作系统调度的基本单位就是线程)就可能会被分配到这两个核心上同时执行。如果此时当前计算机系统相对来说处于一种比较忙碌的状态那么他们就只能排队执行交替执行。
我也想起我之前的某一位Java老师认为没有多线程现在的操作系统只能顺序执行程序计算机只能执行一个进程这种看法是只站在一个Java这一种语言来考虑问题存在一定的认知谬误我想原因大概在于大概在于Java为人熟知最多的就是多线程API这常常给人一种错觉。其实Java也提供了创建进程的API:
private static void createProcess() throws IOException { Runtime runTime Runtime.getRuntime(); // 在单独的进程中执行传入的命令 runTime.exec(“”); ProcessBuilder processBuilder new ProcessBuilder(); // 开启一个进程 processBuilder.start(); } 进程和线程都是操作系统提供的概念操作系统引入进程是为了并发的执行程序引入线程则是为了为了更好的共享资源、节省资源。那么多核碰见并发执行程序就擦出了火花当多个处理器的运算任务涉及同一块主内存区域时将可能导致各自的缓存数据不一致的情况为了解决这个问题就需要制定规则这也就是缓存一致性协议这类的协议有MSI、MESI、MOSI等等。
MESI协议简介 当CPU写数据时如果发现操作的变量是共享变量即在其他COU也存在该变量的副本会发出信号通知其他CPU将变量的缓存行设置为无效状态因为当其他CPU需要读取这个变量时发现自己缓存中缓存该变量的缓存行是无效的那么它就会从内存中重新获取。缓存行的中具体的几种状态如下
iLPvaZ.jpeg
我们现在举个例子来说明体会一下缓存一致性协议为了讨论问题方便我们现在的处理器只有两核心也就是两个CPU, 现在主内存有一个变量x 1MESI的工作流程为
假设CPU1需要读取x的值此时CPU1从主内存中读取到缓存行后的状态为E代表只有当前数据中独占数据并利用CPU嗅探机制监听总线中是否有其他缓存读取x的操作。 此时如果CPU2也需要读取x的值到缓存行则CPU2中缓存行的状态为S表示多个缓存中共享同时CPU1由于嗅探到CPU2也缓存了x所以状态也变成了S。并且CPU1和CPU2会同时嗅探是否有令缓存失效获取独占的操作。 当CPU1有写入操作需要修改x的值时CPU1中缓存行的状态就变成了M。 CPU2由于嗅探到了CPU1的修改操作则会将CPU2中缓存的状态变为I无效状态。 此时CPU1中缓存行的状态重新变回独占E的状态CPU2要想读取x的值的话需要重新从主内存中读取。 状态变化图如下
iLTWzw.jpeg
写缓冲器与无效化队列 MESI协议解决了缓存一致性问题但是其自身也存在一个性能弱点-处理器执行写内存操作时必须等待其他所有处理器将其高速中相应副本数据删除接收到这些处理器所回复的消息之后才能将数据写入高速缓存。为了规避和减少这种等待造成的写操作的延迟硬件设计者引入了写缓冲器和无效化队列。写缓冲器是处理器内部的一个容量比高速缓存还小的部件每个处理器都有其写缓冲器一个处理器无法读取另外一个处理器上的写缓冲器中的内容。