3,进程间通信IPC机制,线程,线程通信,互斥锁

mac2022-06-30  25

今日内容: 1,进程间的相互通信 2,生产者消费者模型 3,线程 4,线程间通信 5,线程互斥锁 1,进程间相互通信 IPC 机制 1,基于队列来实现通信Queue,队列就相当于管道+锁 队列:先进先出 堆栈:先进后出 from multiprocessing import Queue q = Queue(5) # 括号内可以传参数 表示的是这个队列的最大存储数 q.put(1) q.put(2) q.put(3) q.put(4) q.put(5) 向队列中添加数据 print(q.full()) 判断队列是否满了,Ture 或 False q.get() q.get() print(q.empty()) 判断队列中的数据是否被取完 print(q.get()) 从队列中获取数据 print(q.get()) print(q.get()) print(q.get_nowait()) # 取值 没有值不等待,直接报错 ps:get与put要对应,数量一致,put一次只能从队列中添加一个值,get一次只能拿出一个值 如果get的数量比put的多,则队列中的值被取完了,此时不会报错, 就会等待(阻塞),等队列中有值加入时,继续取值操作,同理 put增加值时也是一样的 即q.put(6) # 当队列满了之后 再放入数据 不会报错 会原地等待 直到队列中有数据被取走(阻塞态) 当队列中的数据被取完之后 再次获取 程序会阻塞 直到有人往队列中放入值 补充: full(), q.empty(), q.get_nowait() 都不适用于多进程的情况下 案列: from multiprocessing import Process,Queue def scz(q): 要把队列的对象传进来***** q.put('hello') def xfz(q): print(q.get()) if __name__ == '__main__': q = Queue() p = Process(target=scz,args=(q,)) p1 = Process(target=xfz,args=(q,)) p.start() p1.start() 总结:两个进程之间通信,是通过队列来实现的,把 产生的数据放在队列中,让另一个进程提取 在这里要注意的是要把队列对象作为参数分别传给两个进程 2,生产者消费者模型 问题:解决供需不平衡的问题 生产者:生产或者制造数据的 做包子的 消费者:来筛选或者处理数据 买包子的 案列:(不能让阻塞在data = q.get()位置) from multiprocessing import Process,JoinableQueue,Queue import time import random def scz(name,food,q): for i in range(0,10): data = ('%s生产了%s包子%s'% (name,food,i)) time.sleep(0.5) q.put(data) print(data) def xfz(name,q): while True: data = q.get() if data == None: break # 如果data为None,说明队列中的数据已被取完 print('%s 吃掉了%s包子'% (name,data)) time.sleep(random.random()) q.task_done() # 告诉队列从队列中已取出一个数据,并且已经全部处理完毕,结束任务 ***** if __name__ == '__main__': # q = Queue() q = JoinableQueue() # ******* p = Process(target=scz, args=('111', '牛肉馅', q)) p1 = Process(target=scz, args=('盘龙', '白菜馅', q)) c = Process(target=xfz, args=('开门', q)) c1 = Process(target=xfz, args=('芝麻', q)) c.daemon = True c1.daemon = True p.start() p1.start() c.start() c1.start() #这种方法太low了 # p.join() # 确保生产者确确实实生产完了 # p1.join() # 确保生产者确确实实生产完了 # q.put(None) # 生产者生产完在队列增加一个值 None, 当取值取到None时说明队列中的数据取完了 # q.put(None) # 一个消费者用一个None,两个消费者就得用两个None ,一个消费者只要接受到none,立马结束! # 高级方法 p.join() # 确保生产者确确实实生产完了 p1.join() q.join() # 等到队列中的数据全部被取出 ******* 3,线程 1,线程:最小的执行单位 2,进程:资源单位 将内存比作工厂,那么进程就是车间,线程就是车间里的流水线 ps:每个进程都自带一个主线程,线程是最小的执行单位,进程只是为了给线程提供资源或者代码 在进程中,每个线程都是共享进程资源 开启线程的销号要远远小于进程 进程:开辟内存空间,太耗资源 拷贝代码: 耗资源 开启线程的两种方式: ps:开线程不需要在__main__代码块内 但是习惯性的还是写在__main__代码块内 from threading import Thread import time def task(name): print('tttttu%s'% name) time.sleep(1) print('11111') p = Thread(target=task,args=('teek',)) p.start() 告诉操作系统开辟一个线程 线程的开销远远小于进程 print('zhu') 第二种方式: class MyThread(Thread): def __init__(self,name): super().__init__() self.name = name def run(self): print("%s 是个大帅哥!"% self.name) time.sleep(0.1) print('但是%s疯了!'% self.name) p = MyThread('张文诶诶') p.start() # 启动线程 print('zhu') 线程的其他方法: from threading import Thread,current_thread,active_count 1,current_thread 查看主线程或者子线程 print('子current_thread:',current_thread().name) 线程没有自主之分,都是平等的,在这里为了区分,才这样讲 2,active_count 查看线程是否存活 print('当前正在活跃的线程数',active_count()) 3,获取子线程号 print('子',os.getpid()) 守护线程: 主线程的结束也就意味着进程的结束 主线程必须等待其他非守护线程的结束才能结束 (意味子线程在运行的时候需要使用进程中的资源,而主线程一旦结束了资源也就销毁了) 案列: from threading import Thread import time def task(i): time.sleep(i) print('tt’) t = Thread(target=task,args=(1,)) t.daemon = True t.start() print('主') 主 4, 线程间通信 同一个进程的资源所有线程都可用,即数据共享 money = 666 def task(): global money money = 999 t = Thread(target=task) t.start() t.join() print(money) 5,线程互斥锁: 当多个线程或者进程想要操作同一份数据时,必须加锁,防止数据错乱! 案列: from threading import Thread,Lock import time n = 100 def task(m): global n m.acquire() tmp = n time.sleep(0.1) n = tmp -1 m.release() tt = [] m = Lock() for i in range(100): t = Thread(target=task,args=(m,)) t.start() tt.append(t) for t in tt: t.join() print(n)

转载于:https://www.cnblogs.com/Fzhiyuan/p/11342037.html

最新回复(0)