《并发概念计算机.docx》由会员分享,可在线阅读,更多相关《并发概念计算机.docx(38页珍藏版)》请在优知文库上搜索。
1、并发概念(计算机)一.串行程序、并发程序、并行程序串行程序:指只能被顺序执行的指令列表。并发程序:并发程序属于程序,其内部是由多个部分(串行程序)组合在一起,这些部分组合在一起构成了一个整体,叫做并发程序。也叫单元并行程序:指可以在并行的硬件上(CPU,服务器),运行的并发程序。二、并发系统、并行系统并发系统:程序和程序之间是通过协议协商一致后形成通信。并发系统就是多个并发程序间构成的,看作是一个系统。并行系统:指并发系统以并行的方式存在。每个并发系统中的程序,很有可能会部署在多个并行硬件上(服务器)同时运行,也叫做分布式系统。三、并发程序内部交互1 .什么是并发程序的内部交互?并发程序中存在
2、多个串行程序,这些串行程序之间可能会存在数据交互的需求。比如多个串行程序对一个共享资源进行访问(数据库,消息队列);又或者在它们之间传递一些数据。在这些需求的环境下,协调它们的执行,就要涉及到同步。2 .同步的作用避免在并发访问共享资源时发生的冲突,可以有条不紊的传递数据。3 .同步的原则当程序要访问一个共享资源时,就必须请求该共享资源并获取对应的访问权;反之如果程序不再需要一个共享资源,就要放弃该资源的访问权。(释放资源,Close()而应该等到其释放资源后在进行访问(锁)。结论:一个共享资源在同一时刻内,只能被一个程序占用。同步会导致系统资源的浪费,耦合性太强。所以有了异步通信的思想。4
3、.异步通信发送方可以不加延迟的将消息发送出去,接收方也不会造成发送方的等待。(解耦)数据会被临时存储在一个通道缓存(IPC)的通道中。通道缓存是一种特殊的共享资源,可以被多个程序使用。接收方准备就绪后无需知道发送方,直接从通道缓存中获取数据。多线程编程概念(计算机)一、什么是多线程编程POSIX:可移植性的UniX操作系统接口。NPTL:LinUX操作系统的最新线程库。多线程编程是一种比多进程编程更灵活,更高效的编程方法。在Linux系统中提供了一个以POSIX为标准定义的线程(简称:POSIX线程)为中心的各种系统调用。POSIX也是go并发编程在Iinux系统下真正使用的内核接口,也就是N
4、PTL本地POSIX线程库。二、什么是线程线程可以视为进程中的控制流,一个进程中至少要包含一个线程。因为一个进程中至少要一个控制流持续运行。所以第一个线程会随着其进程的启动而创建,这个线程也被称之为主线程。一个进程中可以存在多个线程,这些线程是由当前进程中存在的线程创建出来的,而创建的方法就是系统调用。更准确的说是调用pthread_create函数。拥有多个线程的进程可以并发执行多个任务,并且即使某个线程被阻塞也不会影响到进程中其它任务的执行。线程会大大提升程序的响应效率和吞吐量线程不能独立于进程之上,线程的生命周期不能超过其所在进程的生命周期。三、如何实现一个线程通过系统调用来控制线程。线
5、程与进程的父子家族关系树结构不同,线程之间的关系都是平等的。它们之间不存在层级关系,任何线程都可以对同一进程中的其它线程进行有效的管理。其中管理分为5种:pthread_create创建线程pthread_cancel终止线程pthread_join连接已经终止线程pthread_detach分离线程pthread_exit彻底退出主线程3-1V线程TID标识和进程一样,线程也有属于自己的ID,叫做TIDo但与进程不同的是,线程ID在系统内中并不唯一,只会在其当前进程下唯一。不过Iinux系统则确保了每个线程在系统内ID的唯一性。目当某个线程不复存在后,其TID可以被其它线程复用。线程ID由操
6、作系统内核进行分配和维护。四、线程运行时发生异常会怎么样线程异常后会强制调用pthread,cancel函数来终止线程,然后调用detach函数分离线程。根据不同的异常情况会进入僵死状态和终止状态两种。僵死状态就是还会保留一些程序所需的资源,不会删掉线程上的全部数据。如果不再需要僵死线程,就会调用PthreadJoin终止掉僵死线程。五、如何在两个线程间共享数据一个进程中的所有线程都拥有自己的线程栈,并以此来存储线程私有的数据栈。这些线程的线程栈包含在其所属进程的虚拟内存空间当中。一个进程中的很多资源都会被其所有线程共享,这些被线程共享资源包括(在当前进程的虚拟内存中存储的):数据段、代码段、
7、堆、栈、信号,以及当前进程支持的文件描述符。正因如此,同一个进程中的多个线程运行的肯定是一个程序。只不过具体的流控方式会有所不同。另外,创建一个线程也不会像创建进程那样费劲,因为线程需要的所有代码、数据段、资源都在其进程中存储不需要被复制就能使用。操作系统内核提供了若干系统调用以便应用程序能够管理当前进程中的所有线程,还可以通过相应的系统功能协调这些线程的运行。六、线程状态线程状态分为:1 .就绪状态2 .运行状态3 .阻塞状态4 .睡眠状态当调用pthread_create函数时线程会进入就绪状态。当线程获得运行时机被CPU激活运行之后会进入运行状态。在线程运行中如果出现了阻塞等待,就会进入
8、睡眠状态,阻塞解除后会重新进入就绪状态。在线程运行中如果出现了return语句,或者退出线程的语句,根据当时不同的线程执行环境会进入僵尸状态和终止状态。不管是僵尸状态还是终止状态最终都会被回收。七、线程调度在线程的生命周期中,操作系统内核对线程的调用是非常核心的部分。正是因为有了调度器的实时调度和切换,才给众多线程一种并行运行的幻觉。调度器会把事件划分成极小的时间片,并把这些时间片分配给不同的线程,以使众多线程都有机会在CPU上运行。一个线程什么时候能够获得CPU时间,以及在CPU上运行多久,都是调度器的工作范畴。调度器:最大程度保证多核CPU之间的平衡运行。7-1.什么是线程调度,什么是线程
9、切换线程调度(也称线程间的上下文切换),线程的执行总是趋向于CPU受限或者I/O受限。也就是说线程的调度只分为两类:一些线程需要花费一定的时间使用CPU进行计算,另一些线程会花费一些时间等待相对较慢的I/O操作完成。调度器会依据它对线程的趋向性的猜测把他们进行分类,并让I/O受限的线程具有更高的动态优先级以及优先使用CPUo调度器会认为I/O操作往往会花费更长的时间,所以应该让它们尽早执行。这也是为了让众多线程运行的更加高效。在人决定下一个要敲击的按键、磁盘在磁道中定位簇或者网卡从网络中接收数据帧的时候,CPU可以腾出手来位其它线程服务。7-2.线程的静态、动态优先级调用线程的动态优先级是可以
10、被调度器实时调整的,而与之相对应的线程的静态优先级只能由程序指定。如果应用程序没有指定一个线程的静态优先级,那么默认为Oo调度器不会改变线程的静态优先级。线程的动态优先级就是调度器在其静态优先级的基础上调整得出的,动态优先级决定了线程的运行顺序。而线程的静态优先级决定了线程单次在CPU上运行的最长时间,也就是调度器分配给它的时间片的大小。所有等待使用CPU的线程会按照动态优先级从高到低的进行顺序排序,并依序放到与该CPU对应的运行队列当中。因此,下一个运行的线程总是动态优先级最高的那一个。7-3V线程的优先级队列每一个CPU的运行队列中都包含两个优先级阵列。其中一个用于存放正在等待运行的线程,
11、暂时称之为(激活的优先级阵列)。另一个则用于存放正在等待的运行的线程,暂时称为(过期的优先级阵歹I)。下一个运行的线程总是会从激活的优先级队列中选出。如果CPU发现某个线程占用了CPU很久的时间,并且激活的优先级队列中还有优先级与他相同的线程在等待运行,那么调度器就会让那个等待的线程在CPU上运行,而被换下的则进入过期的优先级阵列。当激活的优先级阵列中没有等待运行的线程时,调度器会把这两个优先级阵列的身份互换,之前的激活阵列变成过期阵列,现在的过期阵列变成激活阵列。如此,放入过期的优先级阵列的线程就又有机会运行了。当然,线程并不是总会处于运行和就绪状态。他还有可能会进入阻塞睡眠状态,处于睡眠状
12、态的线程是不能够被调度和运行的。它们会从两个阵列中移除。七、线程模型线程的实现模型分为三个,分别是:用户级线程模型、内核级线程模型、两级线程模型。它们之间最大的差异就在于线程与内核实体(内核调度实体KES)之间的对应关系。内核调度实体就是被内核调度器所调用的实体对象。也被称为内核级线程,是操作系统得最小运行单元。1 .用户级线程模型(M:1):此模型下的线程是由用户级别的线程库全权管理的。线程库并不是内核的一部分,而只是存储在进程的用户空间之中,这些线程的存在对于内核而言是无法感知的。用户级线程并不是内核的调度器的调度对象。对线程的各种管理和协调完全是用户及程序的自主行为,与内核无关。应用程序
13、在对线程进行创建、终止、切换或同步等操作的时候,并不需要让CPU从用户态转变成内核态。2 .内核级线程模型Q:1):该模型下的线程是由内核负责管理的,它门是内核的一部分。应用程序对线程的创建、终止和同步都必须通过内核提供的系统调用来完成(PthreaCL*)。进程中的每一个线程都会与一个KES(内核调度实体)相对应。也就是说,内核可以分别为每一个线程进行调度。由此,内核级线程模型也被称为Ll的线程实现。一对一线程实现消除了多对一线程实现的很多弊端。可以真正的实现线程的并发运行。3 .两级线程模型(M:N):两级线程模型的目标是取前两种模型的精华,去其糟粕,也成为多对多的(M:N)线程实现。与其
14、他模型相比,两级线程模型提供了更多的灵活性。在此模型下一个进程可以与多个KSE(内核调度实体)相关联,这与内核级线程模型相似,不同点在于进程中的线程并不与KES对应,这些应用程序线程可以映射到同一个已经关联的KES上。实现了两级线程模型的线程库,会通过操作系统内核创建多个内核级线程。然后它会通过这些内核级线程对应用程序线程进行调度。大多数此类线程库都可以将这些应用程序线程动态地与内核级线程关联。这样的设计显然使线程的管理工作更加复杂,因为这需要线程库与内核级线程共同努力和协作才能正确、有效的运行。八、线程同步线程同步的目的就是为了更好地协同工作或者维持数据的一致性。1 .共享数据的一致性一个进
15、程所拥有的相当一部分虚拟内存地址都可以被进程中所有线程共享,所以这些共享数据大多是以内存的空间作为载体。如果两个线程同时读取同一块共享内存但获取到的数据却不相同,那么程序很有可能就会出现某种错误。这是因为,共享数据的一致性往往代表着某种约定,而只有在该约定成立的前提下,多线程程序中的各个线程才能够使相应的流程执行正确。换句话说,如果操作的共享数据的结果,总是与约定的结果相同,就说明共享数据的一致性得到了保证。实际上,保证共享数据一致性的最简单最彻底的方法就是使该数据成为一个不变量。例如:常量就是不变量,它不可能被改变,也就不可能出现不一致的情况。因此无论当前程序中有多少个可能访问常量的线程,都不需要采取任何措施。但是程序中不可能都是常量,我们需要通过额外的手段保证被多个线程共享的变量的一致性,这样就有了临界区的概念。2 .临界区临界区是只能被串行化访问或执行的某个资源或者代码,也被称为串行区域。保证临界区有效的最佳方式就是利用同步机制。在针对多线程程序的同步机制中包含了很多同步方法,包括原子性操作和互斥量,以及条件变量。3 .互斥量在同一时刻,只允许一个线程处于临界区之内的约束,称之为互斥(mutex)o每个线程在进入临界区之前,都必须先锁定某个对象,只有成功锁定对象的线程才会允许进入临界区,否则就会阻塞,这种对象被称为互斥对象或互斥量。