多进程

tech2022-07-05  229

1、创建多进程

使用进程池创建多进程

from multiprocessing import Pool import os import time def work(times): print('这是第{}次的任务,由进程编号{}的进程来完成'.format(times,os.getpid())) time.sleep(3) # 模拟耗时任务 if __name__ == '__main__': pool = Pool(3) # 允许3个进程 for i in range(0,10): # range()遵循c的编写风格,所以左开右闭 # pool.apply_async(work,args=(i,)) # 异步的,非阻塞式(asynchronous) pool.apply(work,args=(i,)) # 同步,阻塞式(synchronous) pool.close() # 关闭进程池 pool.join() # 等待子进程结束,主进程才结束,放在close后面

2、多进程之间的通信(读写)

from multiprocessing import Pool,Manager import time import os def read(que): print('读:进程{}启动,父进程{}'.format(os.getpid(), os.getppid())) for i in range(10): print('获取到的数据是{}'.format(que.get())) # 从队列获取一个数据 def write(que): print('写:进程{}启动,父进程{}'.format(os.getpid(),os.getppid())) for i in range(10): que.put('数字%s'%i) # 往队列里放入一个数据 if __name__ == '__main__': print('---------------这是主进程的ID'.format(os.getpid())) # TODO 创建一个进程池 pool = Pool() # TODO 创建一个队列 q = Manager().Queue() # Manager().Queue()创建一个队列 print(q) # 运行进程池中的进程 pool.apply_async(write,args=(q,)) # 异步运行,非阻塞,模拟写入操作 time.sleep(1) pool.apply_async(read,args=(q,)) # 异步运行,非阻塞,模拟读操作 # 关闭进程 pool.close() # 进行保护 pool.join() # 等子线程结束了再结束主进程 print('这是结束,进程id是',os.getpid())

3、相同进程内的多线程之间共享资源

多线程改变全局变量

import threading import time import os num = 0 def func1(): print('当前写入线程正在运行',os.getpid()) global num for i in range(10): num += 1 def func2(): global num print('当前线程读取的全局变量是',num,os.getpid()) if __name__ == '__main__': t1 = threading.Thread(target=func1) # 创建线程1 t1.start() # 启动线程1 t1.join() # 让线程1顺利执行完毕 time.sleep(1) # 让读操作顺利进行,这个间隔先用来完成写操作 t2 = threading.Thread(target=func2) # 创建线程1 t2.start() # 启动线程2 t2.join() # 让线程1顺利执行完毕 print(num) # 当前写入线程正在运行 11798 # 当前线程读取的全局变量是 10 11798 # 10 # 经过写操作改变了num值,可以看到,在线程2读到的num值为10,主进程中最后读到的num值也为10 # 结论:多线程之间可以共享全局变量

4、重写线程并且探究局部变量

import threading class MyThread(threading.Thread): def __init__(self,num): super(MyThread,self).__init__() self.num = num def run(self): self.num += 1 print('当前调用run方法',self.num) if __name__ == '__main__': t1 = MyThread(0) t2 = MyThread(10) t1.start() t2.start() # 当前调用run方法 1 # 当前调用run方法 11 # 结论:在多线程开发中,全局变量是多个线程都共享的,而局部变量是各自的线程的,不能共享

5、多线程的缺点

不同线程争抢资源引发全局变量不满足预期值的问题

5.1 使用锁来解决

import threading lock = threading.Lock() # 创建互斥锁,让一个线程占用资源时,锁定资源,不让其他线程使用,执行完还需要释放锁 num = 0 def work1(times): global num for i in range(times): flag = lock.acquire(True) # 生成锁 if flag: num += 1 lock.release() # 释放锁 print('在当前的线程work1中,修改过后的num是',num) def work2(times): global num for i in range(times): flag = lock.acquire(True) if flag: num += 1 lock.release() print('在当前的线程work2中,修改过后的num是', num) if __name__ == '__main__': t1 = threading.Thread(target=work1,args=(1000000,)) t2 = threading.Thread(target=work2,args=(1000000,)) # 两个当中有一个执行成功,但不一定是谁 t1.start() # 启动线程1 t2.start() # 启动线程2

5.2 锁带来的死锁现象

各个线程占用资源却又想要获得对方的资源,但又不释放自己占有的资源,就是死锁。

5.3 队列解决死锁问题

通过队列(第三方平台)来实现双方的通信,提升了效率,使得当资源短缺时,经过等待可以让程序继续进行,不会出现死锁。

import threading from queue import Queue # 生产者的线程类 class Producer(threading.Thread): def run(self): global que while True: if que.qsize() < 10: # qsize()队列的大小<10 que.put('生产数据') # 往队列放入一个数据 # 消费者的线程类 class Consumer(threading.Thread): def run(self): global que while True: if que.qsize() > 0: print(self.name,'消费数据',que.get()) # 从队列取出一个数据 if __name__ == '__main__': # TODO 创建队列 que = Queue() # TODO 创建一个线程代表生产者 p = Producer() # TODO 启动生产者 p.start() # TODO 创建一个线程代表消费者 c = Consumer() # TODO 启动消费者 c.start()
最新回复(0)