Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

Gray-Ice

个人博客兼个人网站

转载自v3u.cn

进程,是执行中的计算机程序。也就是说,每个代码在执行的时候,首先本身即是一个进程。

一个进程具有:就绪,运行,中断,僵死,结束等状态(不同操作系统不一样)。

生命周期:

用户编写代码(代码本身是以进程运行的)

启动程序,进入进程“就绪”状态

操作系统调度资源,做“程序切换”,使得进程进入“运行”状态

结束/中断

特性

每个程序,本身首先是一个进程

运行中每个进程都拥有自己的地址空间、内存、数据栈及其它资源。

操作系统本身自动管理着所有的进程(不需要用户代码干涉),并为这些进程合理分配可以执行时间。

进程可以通过派生新的进程来执行其它任务,不过每个进程还是都拥有自己的内存和数据栈等。

进程间可以通讯(发消息和数据),采用 进程间通信(IPC) 方式。

说明

多个进程可以在不同的 CPU 上运行,互不干扰

同一个CPU上,可以运行多个进程,由操作系统来自动分配时间片

由于进程间资源不能共享,需要进程间通信,来发送数据,接受消息等

多进程,也称为“并行”。

进程间通信

进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的。

进程队列queue

不同于线程queue,进程queue的生成是用multiprocessing模块生成的。

在生成子进程的时候,会将代码拷贝到子进程中执行一遍,及子进程拥有和主进程内容一样的不同的名称空间。

multiprocess.Queue 是跨进程通信队列

常用方法

1
2
3
4
5
6
7
q.put方法用以插入数据到队列中,put方法还有两个可选参数:blocked和timeout。如果blocked为True(默认值),并且timeout为正值,该方法会阻塞timeout指定的时间,直到该队列有剩余的空间。如果超时,会抛出Queue.Full异常。如果blocked为False,但该Queue已满,会立即抛出Queue.Full异常。
q.get方法可以从队列读取并且删除一个元素。同样,get方法有两个可选参数:blocked和timeout。如果blocked为True(默认值),并且timeout为正值,那么在等待时间内没有取到任何元素,会抛出Queue.Empty异常。如果blocked为False,有两种情况存在,如果Queue有一个值可用,则立即返回该值,否则,如果队列为空,则立即抛出Queue.Empty异常.
q.get_nowait():同q.get(False)
q.put_nowait():同q.put(False)
q.empty():调用此方法时q为空则返回True,该结果不可靠,比如在返回True的过程中,如果队列中又加入了项目。
q.full():调用此方法时q已满则返回True,该结果不可靠,比如在返回True的过程中,如果队列中的项目被取走。
q.qsize():返回队列中目前项目的正确数量,结果也不可靠,理由同q.empty()和q.full()一样

管道pipe

管道就是管道,就像生活中的管道,两头都能进能出

默认管道是全双工的,如果创建管道的时候映射成False,左边只能用于接收,右边只能用于发送,类似于单行道

1
2
3
4
5
6
7
8
9
10
11
12
import multiprocessing

def foo(sk):
sk.send('hello world')
print(sk.recv())

if __name__ == '__main__':
conn1,conn2=multiprocessing.Pipe() #开辟两个口,都是能进能出,括号中如果False即单向通信
p=multiprocessing.Process(target=foo,args=(conn1,)) #子进程使用sock口,调用foo函数
p.start()
print(conn2.recv()) #主进程使用conn口接收
conn2.send('hi son') #主进程使用conn口发送

常用方法

1
2
3
conn1.recv():接收conn2.send(obj)发送的对象。如果没有消息可接收,recv方法会一直阻塞。如果连接的另外一端已经关闭,那么recv方法会抛出EOFError。
conn1.send(obj):通过连接发送对象。obj是与序列化兼容的任意对象
注意:send()和recv()方法使用pickle模块对对象进行序列化

共享数据manage

Queue和pipe只是实现了数据交互,并没实现数据共享,即一个进程去更改另一个进程的数据。

注:进程间通信应该尽量避免使用共享数据的方式

进程池

开多进程是为了并发,通常有几个cpu核心就开几个进程,但是进程开多了会影响效率,主要体现在切换的开销,所以引入进程池限制进程的数量。

进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止。

线程

线程,是在进程中执行的代码。

一个进程下可以运行多个线程,这些线程之间共享主进程内申请的操作系统资源。

在一个进程中启动多个线程的时候,每个线程按照顺序执行。现在的操作系统中,也支持线程抢占,也就是说其它等待运行的线程,可以通过优先级,信号等方式,将运行的线程挂起,自己先运行。

使用

用户编写包含线程的程序(每个程序本身都是一个进程)

操作系统“程序切换”进入当前进程

当前进程包含了线程,则启动线程

多个线程,则按照顺序执行,除非抢占

特性

线程,必须在一个存在的进程中启动运行

线程使用进程获得的系统资源,不会像进程那样需要申请CPU等资源

线程无法给予公平执行时间,它可以被其他线程抢占,而进程按照操作系统的设定分配执行时间

每个进程中,都可以启动很多个线程

说明

多线程,也被称为”并发“执行。

评论



愿火焰指引你