IO密集型和计算密集型、线程和进程

io密集型:有阻塞的状态,就是一直会执行CPU(中间就一个等待状态,这个就叫做IO密集型)。例如:sleep状态

计算密集型任务:没有等待的状态就是计算密集型,从上到下执行没有等待。

在Python中没法同时使用多个CPU,在同一时刻,多个线程是互相抢占资源的,在cpython运行中加了一把锁(GIL)。

如果任务是IO密集型的可以使用多线程(阻塞等待时,就是放GIL,给另一个线程执行的机会)

如果是计算密集型任务时,无法使用多线程(如果遇到CPU密集型的线程,一只占用CPU,不会被I/O阻塞)

全局解释锁(GIL):就是一个互斥体,只允许一个线程来控制Python解释器。

线程是操作系统调度的最小单元,进程是操作系统分配存储资源的最小单位。

进程:进程表示一个逻辑控制流,就是一种计算过程,他造成一种假象,好像这个进程在独占CPU资源,进程拥有一个独立虚拟内存地址空间。

并发的本质是在时间上重叠多个逻辑流,也就是说同时运行多个逻辑流,并发编程要解决一个很重要的问题就是对资源的并发访问问题,也就是共享资源问题,而两个进程很难在逻辑上共享资源。

线程解决的最大问题就是他可以很简单的表示共享资源问题,也就是存储器资源,资源最后都要加载到物理内存,一个进程的所有线程都是共享这个进程的同一个虚拟地址空间的,也就是从线程的

角度来说,他们看到的物理资源都是一样的,这样就可以通过共享变量的方式来表示共享资源,也就是直接共享内存的方式解决了线程通信的问题,而线程也表示一个独立的逻辑流,这样就解决了

进程的一大难题。

 

进程采用fork创建,线程采用done创建。

进程fork创建的子进程的逻辑流位置在fork返回的位置,线程done创建的KSE的逻辑流位置在done调用传入的方法位置。

进程拥有独立的虚拟内存地址空间,和内核数据结构(页表打开文件表等),当子进程修改了虚拟页之后,会通过写时拷贝创建真正的物理页。线程共享进程的虚拟地址空间和内核数据结构,共享同样的物理页。

多个进程通信只能采用进程间通讯的方式,比如信号、管道而不能直接采用简单的共享内存方式,原因是每个进程维护独立的虚拟内存空间,所以每个进程的变量采用的虚拟地址是不同的。多个线信通信就很简单

直接采用共享内存的方式,因为不同线程共享一个虚拟内存地址空间,变量寻址采用同一个虚拟内存。

进程上下文切换需要切换页表等重量级资源,线程上下文切换只需要切换寄存器等轻量级数据

进程的用户栈独享栈空间,线程的用户栈共享虚拟内存中的栈空间,没有进程高效

一个应用程序可以有多个进程,执行多个程序代码,多个线程只能执行一个程序代码,共享进程的代码段

进程采用父子结构,线程采用对等结构

 

posted @ 2019-01-11 11:42  jacky912  阅读(2777)  评论(1编辑  收藏  举报