程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程。程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述文本;进程是程序的一次执行活动,属于动态概念。
在多道编程中,我们允许多个程序同时加载到内存中,在操作系统的调度下,可以实现并发地执行。这是这样的设计,大大提高了CPU的利用率。进程的出现让每个用户感觉到自己独享CPU,因此,进程就是为了在CPU上实现多道编程而提出的。
有了进程为什么还要线程?
进程有很多优点,它提供了多道编程,让我们感觉我们每个人都拥有自己的CPU和其他资源,可以提高计算机的利用率。很多人就不理解了,既然进程这么优秀,为什么还要线程呢?其实,仔细观察就会发现进程还是有很多缺陷的,主要体现在两点上:
进程只能在一个时间干一件事,如果想同时干两件事或多件事,进程就无能为力了。
进程在执行的过程中如果阻塞,例如等待输入,整个进程就会挂起,即使进程中有些工作不依赖于输入的数据,也将无法执行。
线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务
一、多进程的创建方法
多进程和多线程的使用方法基本一样,只是导入的模块不同,方法是一样的
import threading #线程的模块
threading.Thread(target=,args=()) #执行线程采用的方法
import multiprocessing #进程的模块
multiprocessing.Process(target=,args=()) #执行进程采用的方法
二、进程之间数据共享
进程之间数据共享用multiprocessing的Manager方法
#!/usr/bin/env python
#-*- coding:utf-8 -*-
from multiprocessing import Process, Manager
def MemoryManger(dic, lis):
dic['aaa'] = 'xyz'
dic[1] = 111111
dic['2'] = 222222
dic[0.25] = None
lis.append('xyz')
#print(lis)
if __name__ == '__main__':
with Manager() as manager:
m_dict = manager.dict() #生成一个字典
m_list = manager.list(range(5)) #生成一个列表
res_list = []
for i in range(10):
p = Process(target=MemoryManger, args=(m_dict, m_list))
res_list.append(p)
for res in res_list:
res.start()
res.join()
print(m_dict)
print(m_list)
三、进程池(同一时间有多少个进程在CPU上运行)
进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止。
from multiprocessing import Pool
import time,os
def Foo(num):
time.sleep(1)
print('this process pid is %s' % os.getpid())
return num + 100
def Bar(arg):
'''
这个是一个回调函数,主进程回调的
:param arg:
:return:
'''
print('--> exec done',arg,os.getpid())
if __name__ == '__main__':
pool = Pool(5)
print('main process pid is %s' % os.getpid()) #主进程的pid
for i in range(10):
pool.apply_async(func=Foo,args=(i,),callback=Bar) #回调函数是由主进程调用的
print('end'.center(20,'='))
pool.close() #进程池中进程执行完后再关闭
pool.join()
备注:
1、进程是有两个方法,apply(串行方式),apply_async(并行方式)
2、在关闭的时候,必须是先close,再join。这个顺序不能颠倒
四、进程之间相互通信
不同进程间内存是不共享的,要想实现两个进程间的数据交换,需要一个中间件(队列或者管道)
1、队列
#!/usr/bin/env python
#-*- coding:utf-8 -*-
from multiprocessing import Process, Queue
def f(q):
q.put(['id','name','age'])
if __name__ == '__main__':
q = Queue()
p = Process(target=f, args=(q,))
p.start()
print(q.get()) #从队列里面取值
p.join()
备注:
在生成进程的时候,先把 q 传进去,但实际上是克隆了一份(在 f 函数里面),在传进去的时候,即生成进程的时候,pickle序列化了一下,当线程访问的时候,又pickle反序列化。
2、管道
#!/usr/bin/env python
#-*- coding:utf-8 -*-
from multiprocessing import Process, Pipe
def f(conn):
conn.send(['id','name','age'])
conn.close()
if __name__ == '__main__':
parent_con, child_con = Pipe()
p = Process(target=f, args=(child_con,))
p.start()
print(parent_con.recv()) # prints "[42, None, 'hello']"
p.join()