当前位置: 首页 > 科技观察

并发编程从对操作系统底层工作的整体理解开始

时间:2023-03-15 10:04:11 科技观察

前言在多线程、多处理器、分布式环境下编程的时代,并发是一个无法回避的问题。既然并发问题是摆在我们面前无法回避的一道坎,不如拥抱它,搞清楚它,花一定的时间从操作系统的底层原理到基础的编程,深入探索并发问题。Java到分布式环境。.我们先从原理说起。计算机系统的层次结构早期计算机系统的层次结构最早的计算机是用机器语言编程的,称为第一代编程语言汇编语言编程汇编语言编程现代(传统)计算机系统的层次结构现代计算机是用高级语言编程的第三代编程语言(3GL)是过程式语言,编码时需要描述实现过程,即“怎么做”。第四代编程语言(4GL)是一种非过程语言。它只需要在编码时解释“要做什么”,而不需要描述具体的算法实现细节。语言处理系统包括:各种语言处理程序(如编译、汇编、链接)、运行时系统(如库函数、调试、优化等),操作系统包括人机交互界面,内核例程提供服务功能。大纲:语言的发展是一个不断“抽象”的过程。因此,相应的计算机系统也不断有新的层次出现。计算机系统抽象层改造功能改造:上层是对下层的抽象,下层是对上层的实现。底层为上层提供支撑环境!计算机系统的不同用户最终用户工作在应用程序提供的最顶层抽象层,系统管理员工作在操作系统提供的抽象层,应用程序员工作在语言处理系统(主要是编译器和汇编器)的抽象层)语言处理系统建立在操作系统之上系统程序员(实现系统软件)在ISA级别工作编译器和汇编器的目标程序由机器级代码组成,操作系统直接对硬件进行编程和控制通过说明。ISA处于软件和硬件之间的接口(interface)。ISA是硬件的抽象。集成了所有软件功能。建立在ISA之上的指令集架构(ISA)ISA指的是InstructionSetArchitecture,即指令集架构,有时也称为指令系统ISA是一种规范(Specification),规定了如何使用一组硬件-可执行指令,包括指令格式、操作类型,以及每个操作对应的操作数的相应规定;指令可以接受的操作数类型;操作数可以存放的寄存器组的结构,包括名称、编号、长度和用途;操作数可存放的存储空间大小及寻址方式;操作数按大端或小端存储在存储空间中;指令获取操作数的方式,即寻址方式;指令执行过程的控制方式,包括程序计数器(PC)、条件码定义等。ISA是通用计算机系统中必不可少的抽象层。没有它,软件就无法使用计算机硬件!没有它,计算机就不能称为“通用计算机”ISA与计算机组成(微观结构)的关系ISA是对计算机组件的抽象。不同的ISA规定的指令集是不同的。例如,IA-32、MIPS、ARM等计算机组件必须能够实现ISA规定的功能,如提供GPR、符号、运算电路等。同一个ISA可以有不同的计算机组件。例如,乘法指令可以用ALU或乘法器来实现。现代计算机模型基于冯·诺依曼计算机模型。1946年,普林斯顿高等研究院(IAS)开始设计“存储程序”计算机,称为IAS计算机。冯·诺依曼结构最重要的思想是“存储程序(Stored-program)”工作方式:计算机要做的任何工作,都必须先写入程序,再将程序和原始数据写入主存并开始执行。程序一旦启动,计算机就应该能够自动完成一条一条的取指令和执行指令的任务,而无需操作者的干预。冯诺依曼计算机也称为冯诺依曼机。几乎所有的现代通用计算机大都采用冯·诺依曼结构,因此IAS计算机是现代计算机的雏形。计算机运行时,首先从内存中取出第一条指令,通过控制器的译码,根据指令的要求,从内存中取出数据,进行指定的计算和逻辑运算等,然后根据地址将结果发送给计算机。内存去。接下来取出第二条指令,在控制器的指挥下完成指定的操作。等等。直到遇到停止命令。像数据一样存储程序,按照编程的顺序一步步取出指令,自动完成指令指定的操作,是计算机最基本的工作模式。该原理最早由美匈数学家冯诺依曼于1945年提出,故称为冯诺依曼计算机模型。什么是冯诺依曼结构?有一个主存储器,用于存储程序和数据。一个自动一条一条取指令的组件。专门执行指令(即运算)的组件。程序由指令组成。指令描述了如何处理数据。冯·诺依曼结构计算机的主要思想应该由计算器(calculator)、控制器、存储器、输入设备和输出设备五个基本部件组成。各基本部件的功能是:控制器(Control):是整个计算机的中枢神经,其作用是解释程序指定的控制信息,按其要求进行控制,调度程序、数据、地址、并协调计算机各部分的工作以及对内存和外围设备的访问。计算器(Datapath):计算器的作用是对数据进行各种算术运算和逻辑运算,即对数据进行处理。存储器(Memory):存储器的作用是存储程序、数据以及各种信号和命令等信息,并在需要时提供这些信息。输入(Inputsystem):输入设备是计算机的重要组成部分。输入设备和输出设备组合成外部设备,简称外设。输入设备的作用是将程序、原始数据、文本、字符、控制指令或现场输入数据等信息输入计算机。常见的输入设备有键盘、鼠标、光电输入机、磁带机、磁盘驱动器、光驱等。输出(Outputsystem):输出设备与输入设备一样,是计算机的重要组成部分。它输出外部计算机的中间或最终结果、计算机中的各种数据符号和文本或各种控制信号等信息。微型计算机常用的输出设备有显示终端、CRT、打印机、激光打印机、绘图仪、磁带和CD-ROM。指令和数据在内部以二进制表示。每条指令由操作码和地址码组成。操作码表示操作的类型,地址码表示操作数的地址。程序由一系列指令组成。使用“存储程序”工作。现代计算机结构模型是建立在冯·诺依曼计算机理论的抽象和简化模型之上的。它的具体应用是现代计算机中的硬件结构设计:在上面的硬件结构中,有很多配件,但核心只有两部分:CPU、Memory。所以我们重点关注这两个部分。CPU:中央处理器;PC:程序计数器;MAR:内存地址寄存器ALU:算术逻辑单元;IR:指令寄存器;MDR:MemoryDataRegisterGPRs:GeneralRegisterGroup(由若干个通用寄存器组成,早期的累加器)CPUInstructionstructureCPU内部结构控制单元运算单元数据单元控制单元控制单元是整个CPU的指挥和控制中心,它由指令寄存器IR(InstructionRegister)、指令译码器ID(InstructionDecoder)和运算控制器OC(OperationController)协调整个计算机的有序工作极其重要。它根据用户预先编好的程序,依次从内存中取出每条指令,放入指令寄存器IR中,通过指令译码(解析)确定应该进行什么操作,然后根据指令操作控制器OC确定的时间。向相应的组件发送微操作控制信号。运算控制器OC主要包括拍频脉冲发生器、控制矩阵、时钟脉冲发生器、复位电路和启停电路等控制逻辑。运算器运算器是运算器的核心。可以执行算术运算(包括加法、减法、乘法及其加法等基本运算)和逻辑运算(包括移位、逻辑测试或两个值的比较)。相对于控制单元,运算单元是在控制单元的指挥下运行的,即运算单元进行的所有运算都是由控制单元发出的控制信号指挥的,因此它是一个执行单元。存储单元存储单元包括CPU的片内高速缓存Cache和寄存器组,是CPU中暂存数据的地方,等待处理的数据或已经处理完的数据都存放在其中。短时间。寄存器是CPU的内部组件。寄存器具有很高的读写速度,因此寄存器之间的数据传输速度非常快。使用寄存器可以减少CPU访问内存的次数,从而提高CPU的工作速度。寄存器组可分为专用寄存器和通用寄存器。专用寄存器的作用是固定的,分别存放相应的数据;而通用寄存器被广泛使用并且可以由程序员指定。下表列出了CPU关键技术的发展历程和代表性系列。每一项关键技术的诞生都是环环相扣的。这些处理器技术的发展史都围绕着如何让CPU不闲置这一核心目标展开。扩张。CPU缓存结构为了提高执行效率,减少CPU与内存的交互(交互影响CPU效率),现代CPU普遍在CPU上集成了多级缓存架构。常见的是三级缓存结构L1Cache,分为数据缓存和指令Cache,逻辑核心独占L2Cache,物理核心独占,逻辑核心共享L3Cache,所有物理核心共享内存存储空间大小:memory>L3>L2>L1>注册;内存速度顺序:寄存器>L1>L2>L3>内存;注意:缓存由最小的存储块——缓存行(cacheline)组成,缓存行的大小通常为64bytes。缓存行是什么意思?比如你的L1缓存大小是512kb,cacheline=64byte,那么L1就有512*1024/64个cacheline。CPU读取内存数据过程CPU需要获取寄存器X的值,只需要一步:直接读取。CPU获取L1缓存的某个值需要1-3步(或更多):锁定缓存行,取某条数据,解锁。如果不加锁,会很慢。如果CPU要从L2缓存中获取某个值,首先需要从L1缓存中获取,L1中不存在。在L2中,L2开始锁定。加锁后,将L2中的数据复制到L1中,然后执行读L1。流程,以上3步,然后解锁。CPU对L3缓存的访问也是如此,只是先从L3复制到L2,再从L2复制到L1,再从L1复制到CPU。CPU取内存是最复杂的:通知内存控制器占用总线带宽,通知内存加锁,发起内存读请求,等待响应,将响应数据保存到L3(没有则转到L2),然后从L3/2到L1,再从L1到CPU,之后总线解锁。CPU为什么要有缓存?在摩尔定律的指引下,CPU正以每18个月翻一番的速度发展,但内存和硬盘的发展速度却远远落后于CPU。这就造成了高性能内存和硬盘的价格极其昂贵。但是CPU的高速计算需要高速的数据。为了解决这个问题,CPU厂商在CPU中内置了少量的高速缓存,以解决I\O速度与CPU运算速度不匹配的问题。CPU在访问存储设备时,无论是访问数据还是访问指令,都倾向于聚集在一个连续的区域,这就是所谓的局部性原理。时间局部性:如果一个信息项正在被访问,它很可能在不久的将来再次被访问。如循环、递归、重复方法调用等。空间局部性:如果引用了一个内存位置,那么以后附近的位置也会被引用。例如,顺序执行的代码、连续创建的两个对象、数组等。空间局部分性案例:publicclassTwoDimensionalArraySum{privatestaticfinalintRUNS=100;privatestaticfinalintDIMENSION_1=1024*1024;privatestaticfinalintDIMENSION_2=6;privatestaticlong[][]longs;publicstaticvoidmain(String[]args)throwsException{/**初氰*[longsIMENSION]longIMENSION_1=1024*1024;privatestaticfinalintDIMENSION_2=6[];for(inti=0;i