网络编程二:并发、多进程、多进程间的通信
一、并发
操作系统同时运行多个任务。
单核CPU实现多任务的原理:操作系统轮流让各个任务交替执行---QQ执行2us,切换到微信执行2us,再切换到陌陌执行2us............实际上是每个任务在轮流反复执行,但是因为cpu调度执行速度太快了,导致我们感觉所有任务都在同时运行。
多核CPU实现多任务原理:如果任务数量小于CPU数量,那是真正的多任务并行执行;但是实际上操作系统的任务远远多于CPU核数;多出CPU数量的任务实际上,也是轮流调度到每个CPU核心上执行。
并发:看上去一起执行,任务数量多于CPU核心数量
并行:真正一起执行,任务数量小于等于CPU核心数量
实现多任务的方式:
- 多进程模式
- 多线程模式
- 协程模型
- 多进程+多线程模型
二、多进程
对于操作系统而言,一个任务就是一个进程。
进程是操作系统中,程序执行和资源分配的基本单位。
每个进程都有自己的数据段、代码段、堆栈。
多进程库:multiprocessing,跨平台
在linux系统,也可以使用fork多进程。
import time, os, multiprocessing def run(): print("子进程启动--", os.getpid()) time.sleep(3) print("子进程结束--", os.getpid()) if __name__ == '__main__': print("父进程启动--", os.getpid()) p = multiprocessing.Process(target=run) p.start() # 父进程的结束,不会也不能影响子进程的结束 print("父进程结束--", os.getpid())
父进程启动-- 8752 父进程结束-- 8752 子进程启动-- 7532 子进程结束-- 7532
通常情况下,我们需要父进程,等待子进程结束后,才能结束父进程;此时,对子进程p调用join()方法,即可
if __name__ == '__main__': print("父进程启动--", os.getpid()) p = multiprocessing.Process(target=run) p.start()
p.join() # 父进程将等待子进程结束后,才会结束 print("父进程结束--", os.getpid())
父进程启动-- 8720 子进程启动-- 9032 子进程结束-- 9032 父进程结束-- 8720
全局变量,不能在多个进程中共享
import os, multiprocessing num = 100 def run(): print("子进程启动--", os.getpid()) global num num += 1 print("子进程中的num: ", num) print("子进程结束--", os.getpid()) if __name__ == '__main__': print("父进程启动--", os.getpid()) p = multiprocessing.Process(target=run) p.start() p.join() # 全局变量在多个进程中,不能共享 # 在子程中,修改全局变量,对父进程中的全局变量没有影响 # 因为,在创建子进程时,对全局变量做了一个备份;父进程中的num与子进程中的num是两个完全不同的变量 print("父进程中的num: ", num) # 进程之间的变量也是不共享的 p = multiprocessing.Process(target=run) p.start() p.join() print("父进程结束--%s" % os.getpid())
父进程启动-- 9772 子进程启动-- 9292 子进程中的num: 101 子进程结束-- 9292 父进程中的num: 100 子进程启动-- 9572 子进程中的num: 101 子进程结束-- 9572 父进程结束--9772
多进程:这里使用进程池创建多个进程
import time, os, multiprocessing, random def run(name): print("子进程{}启动--".format(name), os.getpid()) start = time.time() time.sleep(random.choice([1, 2, 3])) end = time.time() print("子进程{}结束{}--耗时{}".format(name, os.getpid(), end-start)) if __name__ == '__main__': print("父进程启动--", os.getpid()) # Pool,默认的进程池大小为CPU核心数,这里为2 pool = multiprocessing.Pool() for i in range(3): # 创建进程,放入进程池统一管理 pool.apply_async(run, args=(i,)) # close()方法:调用此方法后,则不能再向进程池添加进程; # close()方法必须在join()方法之前调用 pool.close() # join方法:让父进程,等待子进程结束后,再结束 # pool.join方法:让父进程,等待进程池中所有子进程结束后,再结束 pool.join() print("父进程结束--%s" % os.getpid())
在进程池中,先启动哪个子进程,是没有先后顺序的。
三、进程间的通信
1.使用Queue实现进程间的通信:multiprocessing.Queue
由父进程创建队列,并传递给子进程;接收到队列的子进程,可以共享此队列。
from multiprocessing import Process, Queue
import os,time
def write(q):
print("启动写子进程,", os.getpid())
for chr in ["A", "B", "C", "D"]:
q.put(chr)
time.sleep(1)
print("结束写子进程,", os.getpid())
def read(q):
print("启动读子进程,", os.getpid())
while True:
value = q.get(True)
print("value = ", value)
print("结束读子进程,", os.getpid())
if __name__ == '__main__':
print("启动父进程,", os.getpid())
# 父进程创建队列,传递给子进程使用
q = Queue()
pw = Process(target=write, args=(q,))
pr = Process(target=read, args=(q,))
pw.start()
pr.start()
pw.join()
# pr进程是一个死循环,无法等待其结束;只能强行结束
pr.terminate()
print("结束父进程,", os.getpid())
posted on 2018-10-28 11:13 myworldworld 阅读(162) 评论(0) 收藏 举报