并发

并发是指逻辑控制流在时间上的重叠,其出现在计算机系统很多不同层面上,例如内核级并发和应用级并发。

应用级并发

1. 访问慢速I/O设备

2. 空间释放延迟

3. 服务器多个网络客户端

4. 多核机器并行计算

现 代操作系统提供了三种基本构造并发程序的方法:

1. 进程 进程有自己的虚拟地址空间,由内核调度和维护,通信方法IPC。

2. I/O多路复用

3. 多线程

进程

进程是一个程序的实例,而程序是运行在进程的上下文中,这里的上下文包括了存放在存储器中的代码和数据,栈,通用寄存器,文件描述符,环境变量等。进程提供给程序的抽象:

1. 一个独立的逻辑控制流,独占的使用cpu

2. 私有的虚拟地址空间,独占的使用存储器 因为进程有自己私有的地址空间,所以进程之间需要显式的IPC通信机制,信号,管道(进程组中子进程之间的通信)

当使用fork时,会新创建一个子进程,子进程与父进程用户级有相同的虚拟地址空间的拷贝,包括文本,数据,bss段,堆和栈,文件描述符。

execve函数在当前上下文中加载并运行一个新的程序,它会覆盖现有的地址空间,但是继承原有的文件描述符。  

举例:一个构造并发服务器的自然方法就是,在父进程中接受客户端连接请求,然后创建新的子进程来为每个客户端提供服务。

服务器打开监听的描述符后,在接受请求连接之后,服务器派生一个子进程,这个子进程获得服务器描述符表的完整拷贝,之后子进程关闭监听描述符,且主进程关闭子进程的已连接描述符。由于父子进程中的已连接描述符都指向同一个文件表表项,所以父进程关闭其已连接描述符是至关重要的。

其他概念:

上下文切换:内核为每个进程维持一个上下文,利用上下文切换的机制来对控制进行转移。

用户模式,内核模式:内核模式相当于超级用户,可以有权限访问任何存储器位置和执行指令集中所有的指令。而用户模式不可以访问内核虚拟存储器中的代码。

I/O多路复用:

    select函数:

            输入:称为读集合的描述符集合和该集合的基数   输出:准备好的描述符集合(当且仅当一个从该描述符读取一个字节的请求不会阻塞时,描述符准备好可以读了)  

    I/O多路复用可以用作并发事件驱动程序的基础。输入状态、输出事件到输出状态的转移,事件驱动。

举例:服务器使用I/O多路复用,借助select检测输入事件的发生。当每个已连接描述符准备好可以读时,服务器就为相应的状态执行转移。

相关概念:

     粒度:每个逻辑流每个时间片执行的指令数量

缺点: 编码复杂,粒度越小编码越复杂

多线程编程:

线程就是运行在进程上下文里的逻辑流。每个线程都有自己的线程上下文,栈,程序计数器,通用目的寄存器和条件码。所有的运行在一个进程里的线程共享该进程的整个虚拟地址空间。线程由内核自动调度,并且内核通过一个整数id来识别线程,但是多个线程运行在单一的进程的上下文中,因此共享该进程的堆,代码,共享库,打开的文件。

和一个进程相关的线程组成一个对等池,独立于其他线程创建的线程。 

1) 线程的存储器模型

2) 变量实例的映射

3) 共享变量

相关概念: 信号同步

P(s) 当s非零时,s--,并立即返回,如果s为0,则挂起当前线程,直到s非零

V(s) s++,当有线程被p挂起,则重启这些线程中的一个

Python多线程是单cpu意义上的多线程,它和多cpu上的多线程有着本质的区别。一般情况下,任意时刻只能有一个python线程在运行,所以不可能达到并行的效果。(全局解释器锁)

在python上开启多个线程,由于GIL的存在,每个单独线程都会在竞争到GIL后才可以运行。

而C多线程就可以达到真正意义上的并行,多核CPU上同时运行多个线程。

    

原文地址:https://www.cnblogs.com/Nastukashii/p/4750268.html