共享内存(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)
上一篇:协程 信号量 死锁现象与递归锁 事件event 定时器与线程queue gil解释器锁 多线程性能测试
下一篇:生产_DB2相关操作

发表评论

最新留言

初次前来,多多关照!
[***.217.46.12]2025年03月26日 22时14分59秒