
共享内存(IPC进程间通信) 生产者消费者模型 线程理论 开启线程Thread 线程的相关对象与方法 守护线程 互斥锁
发布日期:2021-05-08 03:56:56
浏览次数:19
分类:精选文章
本文共 5195 字,大约阅读时间需要 17 分钟。
共享内存(IPC进程间通信)
1.管道 一个进程写,一个进程读的情况,两个进程涉及不到数据安全的问题可以用管道来实现共享内存2.队列(管道+锁)
队列使用于本地,不能基于网络通信# 队列代码实现from multiprocessing import Queueq = Queue(3) # 列表里面存的值跟取的值都是放入q里面的,Queue(3)表示队列里面最多只能放3个值,如果超过3个值,那么该队列则处于堵塞状态队列里面放值q.put([1, 2, 3])q.put({ "a": 1})q.put("xxxx")q.put(100000)q.put(1000, block=True, timeout=3) # block=True,可以通过timeout来指定超时时间,队列满了,超时会直接抛出异常q.put(1000, block=False) # block=False,队列满了就直接抛出异常队列里面取值print(q.get())print(q.get())print(q.get())print(q.get(block=False)) # block=False,取不到值就直接抛出异常print(q.get(block=True, timeout=3)) # block=True,可以通过timeout来指定超时时间,取不到值的情况下,超时会直接抛出异常
生产者消费者模型
什么是生产者消费者模型: 该模型有两种角色:一种是生产者,另外一种是消费者 生产者负责产生数据,消费者负责取走数据进行处理生产者与消费者通过队列通信
优点:解耦合,平衡了生成者的生产力与消费者的处理能力
生产者与消费者模型案例方式1()from multiprocessing import Process, Queueimport timeimport randomdef producer(q, name, food): for i in range(3): res = "%s %s" % (food, i) time.sleep(random.randint(1, 3)) q.put(res) print("%s 生成了 %s" % (name, res))def consumer(q, name): while True: res = q.get() if res is None: break time.sleep(random.randint(1, 3)) print("%s 吃了 %s" % (name, res))if __name__ == '__main__': q = Queue() p1 = Process(target=producer, args=(q, "厨师1", "包子")) p2 = Process(target=producer, args=(q, "厨师2", "烧卖")) p3 = Process(target=producer, args=(q, "厨师3", "面条")) c1 = Process(target=consumer, args=(q, "吃货1")) c2 = Process(target=consumer, args=(q, "吃货2")) p1.start() p2.start() p3.start() c1.start() c2.start() p1.join() p2.join() p3.join() q.put(None) q.put(None) print("主进程")逻辑:先造产品,造好产品后,再运行主进程,主进程再增加两个None,按照队列依次取值的特性,最后两次取值只能取到None。
方式2from multiprocessing import Process, JoinableQueueimport timeimport randomdef producer(q, name, food): for i in range(3): res = "%s %s" % (food, i) time.sleep(random.randint(1, 3)) q.put(res) print("%s 生成了 %s" % (name, res)) q.join() # 等队列的值都被取干净了,再结束def consumer(q, name): while True: res = q.get() time.sleep(random.randint(1, 3)) print("%s 吃了 %s" % (name, res)) q.task_done() # 每次执行一次取值都会发送一次信号if __name__ == '__main__': q = JoinableQueue() p1 = Process(target=producer, args=(q, "厨师1", "包子")) p2 = Process(target=producer, args=(q, "厨师2", "烧卖")) p3 = Process(target=producer, args=(q, "厨师3", "面条")) c1 = Process(target=consumer, args=(q, "吃货1")) c2 = Process(target=consumer, args=(q, "吃货2")) c1.daemon = True c2.daemon = True p1.start() p2.start() p3.start() c1.start() c2.start() p1.join() p2.join() p3.join() print("主进程")
线程理论
线程:一条流水线的运行过程(进程里面代码运行的过程就叫线程,与资源无关)
线程是一个执行单位,cup执行的就是线程
进程是一个资源单位 同一进程下的多个线程,共享进程资源;不同进程下的线程是不可以共享资源的线程与进程的关系与差别
1.同一个进程下的多个线程共享该进程的内存资源 2.开启子线程的开销要远远小于开启子进程用户空间线程与内核空间线程
用户空间线程:用户级线程内核的切换由用户态程序自己控制内核切换, 不需要内核干涉,少了进出内核态的消耗,但不能很好的利用多核cpu。 内核空间线程:切换由内核控制,当线程进行切换的时候,由用户态 转化为内核态。切换完毕要从内核态返回用户态。python属于内核空间线程,由cup控制
开启线程的两种方式
开启进程的方式1进程的特性1:开启子线程的开销要远远小于开启子进程from threading import Thread, current_thread # current_threaddef task(): print("%s is running" % current_thread().name) # 先打印这一行,pid是一样的 # current_thread().name 会获得当前线程的名字if __name__ == '__main__': t = Thread(target=task) t.start() print("主线程", current_thread().name) # 再打印这一行,pid是一样的 # current_thread().name 会获得当前线程的名字
进程的特性2:同一个进程下的多个线程共享该进程的内存资源from threading import Threadn = 100def task(): global n n = 0if __name__ == '__main__': t = Thread(target=task) t.start() t.join() print("主线程", n)
开启进程的方式2from threading import Threadclass Mythread(Thread): def __init__(self, name): super().__init__() self.name = name def run(self) -> None: print("%s is running" % self.name)if __name__ == '__main__': t = Mythread("线程1") t.start()
线程相关对象与方法
from threading import Thread, current_thread, active_count,enumerateimport timedef task(): print("%s is running" % current_thread().name) time.sleep(5)if __name__ == '__main__': t = Thread(target=task) t.start() print(t.is_alive()) # is_alive()判断线程是否存活 print(active_count()) # 查看活着的线程数 print(enumerate()) # 显示了一个列表,里面是线程对象
守护线程(了解)
守护进程守护的是主进程的运行时间,守护线程守护的是主进程的生命周期
线程跟进程一样,主线程也是需要等子线程运行结束后,主线程才会结束 守护进程跟守护线程一样,都不能开启子进程或者子线程from threading import Thread, current_thread, active_countimport osimport timedef task(n): print("%s is run" % current_thread().name) time.sleep(n) print("%s is end" % current_thread().name)if __name__ == '__main__': t1 = Thread(target=task, args=(3,)) t2 = Thread(target=task, args=(5,)) t3 = Thread(target=task, args=(100,)) t3.daemon = True t1.start() t2.start() t3.start() print("主")
互斥锁
降低数据运行的效率,保护了数据安全。
from threading import Thread, Lockimport timen = 100mutex = Lock()def task(): global n with mutex: teep = n time.sleep(0.1) n = teep - 1if __name__ == '__main__': thread_l = [] start_time = time.time() for i in range(100): t = Thread(target=task) thread_l.append(t) # 把每一次运行的线程对象添加到列表里面(并发) t.start() for obj in thread_l: obj.join() # 把线程对象依次加上join,这样一个线程抢到锁运行完后,下一次其他线程才能抢锁运行 print("主", n, time.time() - start_time)
发表评论
最新留言
初次前来,多多关照!
[***.217.46.12]2025年03月26日 22时14分59秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
STL笔试面试题总结(干货)(转)
2021-05-09
XML 和 HTML 之间的差异
2021-05-09
阿里钉钉面试题
2021-05-09
华为社招笔试
2021-05-09
C++中找资源或者函数的方法
2021-05-09
一些留给自己的思考题(只求回过头来能够有所获)
2021-05-09
SQL函数返回表的写法
2021-05-09
delete对象时会自动调用类的析构函数
2021-05-09
C++ 子类对象直接赋值给父类对象可行,反过来不行
2021-05-09
linux下同一个动态库名为何辣么多的.so文件
2021-05-09
SQL联表的方式(逗号, Left Join, Right Join)
2021-05-09
牛客网输入输出举例
2021-05-09
字符串初始化时的注意点
2021-05-09
软考相关试题
2021-05-09
顺序表的操作
2021-05-09
常量表达式
2021-05-09
POD类型
2021-05-09
const与常量,傻傻分不清楚~
2021-05-09
Head First设计模式——迭代器模式
2021-05-09
MongoDB版本及存储引擎区别
2021-05-09