zoukankan      html  css  js  c++  java
  • day 34 守护线程守护进程 互斥锁线程 信号量 生产者消费者

    今日内容

    1、守护进程vs 守护线程(*)

    2、互斥锁(**)

    3、信号量(**)

    4、生产者消费者模型(*****)

    5、GIL(什么时候用进程,什么时候用线程)(*****)

    一、守护进程和守护线程

    1、守护进程  (分出去的进程设置成守护进程)

      守护进程不能开启子进程

    #守护进程
    from multiprocessing import Process
    import os,time,random
    
    def task():
        print("%s is running"%os.getpid())
        time.sleep(2)
        print("%s is done"%os.getpid())
        # p=Process(target=time.sleep,args=(3,))
        # p.start()
    
    if __name__=="__main__":
        p=Process(target=task)
        p.daemon=True  #1、
        p.start()
        print("")
    守护进程
    举例说明守护进程的应用场景:
    假设有两个任务要干,要玩出并发的效果,使用进程的话可以让主进程
    执行一个任务,然后开启一个子进程执行一个任务。

    如果这两个任务毫无关系,那么就像上面这么做就可以
    如果主进程的任务在执行完毕后,子进程的任务没有存在的意义了
    那么该子进程应该在开启之前就被设置成守护进程
    # 迷惑人的例子
    # 主进程代码运行完毕,守护进程就会结束
    from multiprocessing import Process
    from threading import Thread
    import time
    def foo():
        print(123)
        time.sleep(1)
        print("end123")
    def bar():
        print(456)
        time.sleep(3)
        print("end456")
    if __name__=="__main__":
        p1=Process(target=foo)
        p2=Process(target=bar)
    
        # p1.daemon=True
        p1.start()
        p2.start()
        print("main___")# 打印该行则主进程代码结束,则守护进程p1应该被终止,
        # 可能会有p1任务执行的打印信息123,因为主进程打印main----时
        # ,p1也执行了,但是随即被终止
    迷惑人的例子

      总结  :主进程运行完毕,守护进程也会随之结束

    2、守护线程 

      一个进程开启了多个线程

     (1)守护线程能开启子线程

    #守护线程:等到该进程内所有非守护线程都运行完才死掉
    from multiprocessing import Process
    from threading import Thread
    import os,time,random
    
    def task():
        t=Thread(target=time.sleep,args=(3,))
        t.start()
        print("%s is running"% os.getpid())
        time.sleep(2)
        print("%s is done"%os.getpid())
    if __name__=="__main__":
        t=Thread(target=task)
        t.daemon=True #1、必须在t.start()之前2:守护线程可以开启子线程
        t.start()
        t.join()
        print("")
    守护线程

    (2)迷惑人的例子  ————守护线程

          其中非守护线程还没有结束(开启线程的目的是为了执行完毕函数)

    #迷惑人的例子:守护线程
    from multiprocessing import Process
    from threading import Thread
    import time
    def foo():
        print(123)
        time.sleep(1)
        print("end123")
    
    def bar():
        print(456)
        time.sleep(2)
        print("end456")
    
    if __name__=="__main__":
        t1=Thread(target=foo)
        t2=Thread(target=bar)
        t1.daemon=True
        t1.start()
        t2.start()
        print("main_____")
    # 123
    # 456
    # main_____
    # end123
    # end456
    迷惑人的例子——守护线程

    3、总结:

        为什么守护进程内不让开启子进程?

        主进程结束之后守护线程就会死掉(在这个进程中所有的非守护线程都运行完)

     主线程什么时候结束?

        主进程死掉(所有的线程结束后) 接着守护进程就会死掉

     二、互斥锁

    1、互斥锁进程

    from multiprocessing import Process,Lock
    import os,time,random
    
    def task():
        print("%s print 1"%os.getpid())
        time.sleep(random.randint(1,3))
        print("%s print 2"%os.getpid())
        time.sleep(random.randint(1, 3))
        print("%s print 3" % os.getpid())
    
    if __name__=="__main__":
        p1=Process(target=task)
        p2=Process(target=task)
        p3=Process(target=task)
        p1.start()
        p1.join()
        p2.start()
        p2.join()
        p3.start()
        p3.join()
    1、low的做法
    from multiprocessing import Process,Lock
    import os,time,random
    
    def task(mutex):
        mutex.acquire()
        print("%s print 1"%os.getpid())
        time.sleep(random.randint(1,3))
        print("%s print 2"%os.getpid())
        time.sleep(random.randint(1, 3))
        print("%s print 3" % os.getpid())
        mutex.release()
    if __name__=="__main__":
        # p1=Process(target=task)
        # p2=Process(target=task)
        # p3=Process(target=task)
        # p1.start()
        # p1.join()
        # p2.start()
        # p2.join()
        # p3.start()
        # p3.join()
        mutex=Lock()
        p1 = Process(target=task,args=(mutex,))
        p2 = Process(target=task,args=(mutex,))
        p3 = Process(target=task,args=(mutex,))
        p1.start()
        p2.start()
        p3.start()
    2、改进的互斥锁方法

    2、模拟抢票的例子

    from multiprocessing import Process,Lock
    import json
    import os,time,random
    
    def search():
        with open("db.txt",encoding="utf-8") as f:
            dic=json.load(f)
            print("%s 剩余票数%s"%(os.getpid(),dic["count"]))
    
    def get():
        with open("db.txt",encoding="utf-8")as read_f:
            dic=json.load(read_f)
    
        if dic["count"]>0:
            dic["count"]-=1
            time.sleep(random.randint(1,3))#模拟手速+网速
            with open("db.txt","w",encoding="utf-8")as write_f:
                json.dump(dic,write_f)
                print("%s 抢票成功"%os.getpid())
    
    def task(mutex):
        search()
        mutex.acquire()
        get()
        mutex.release()
    if __name__=="__main__":
        # for i in range(20):
        #     p=Process(target=task)
        #     p.start()
        #     p.join()
        mutex=Lock()
        for i in range(20):
            p=Process(target=task,args=(mutex,))
            p.start()
            p.join()
    模拟抢票的例子

    3、线程互斥锁

    # 线程互斥锁
    from threading import Thread,Lock
    import time
    n=100
    def task():
        global n
        with mutex:
            temp=n
            time.sleep(0.1)
            n=temp-1
    if __name__=="__main__":
        mutex=Lock()
        t_1=[]
        for i in range(100):
            t=Thread(target=task)
            t_1.append(t)
            t.start()
        for t in t_1:
            t.join()
        print(n)
    线程互斥锁

    三、信号量(和进程池不一样)

    例子:抢公共厕所(假如进去10个人,十把钥匙,结束一个就释放钥匙,然后进去一个)

    1、进程的信号量:

    from multiprocessing import Process,Semaphore
    # from threading import Thread,Semaphore
    import time,random,os
    
    def task(sm):
        with sm:
            print("%s 上厕所"%os.getpid())
            time.sleep(random.randint(1,3))
    
    if __name__=="__main__":
        sm=Semaphore(3)
        for i in range(10):
            for i in range(10):
                p=Process(target=task,args=(sm,))
                p.start()
    信号量

    2、小心锁与锁之间的嵌套

    (1)管道和队列都是用的内存的空间

    (2)队列是基于管道加锁实现的

    (3)如果对管道感兴趣就看博客   队列推荐使用

    3、  进程Queue 和线程Queue 

    不能直接放视频,应该直接放路径或者是链接

    (1)

    from multiprocessing import Queue #进程队列
    
    # import queue  #线程队列
    q=Queue(3)
    
    q.put({"a":1})
    q.put("xxxxx")
    q.put(2)
    q.put(4)
    
    print(q.get())
    print(q.get())
    print(q.get())
    print(q.get())

    (2)队列的功能————先进先出

    from multiprocessing import Queue #进程队列
    import queue  #线程队列
    q=queue.Queue(3)
    q.put({"a":1})
    q.put("xxxxx")
    q.put(2)
    q.put(4)
    
    print(q.get())
    print(q.get())
    print(q.get())
    print(q.get())
    队列
    # 优先级队列
    from multiprocessing import Queue #进程队列
    import queue  #线程队列
    q=queue.PriorityQueue(3)
    q.put((10,{"a":1}))
    q.put((-1,"xxxxx"))
    q.put((0,2))
    
    print(q.get())
    print(q.get())
    print(q.get())
    # (-1, 'xxxxx')
    # (0, 2)
    # (10, {'a': 1})
    优先级队列

    (3)堆栈————后进先出

    # 堆栈
    from multiprocessing import Queue #进程队列
    import queue  #线程队列
    q=queue.LifoQueue(3)
    q.put({"a":1})
    q.put("xxxxx")
    q.put(2)
    
    print(q.get())
    print(q.get())
    print(q.get())
    print(q.get())
    # 2
    # xxxxx
    # {'a': 1}
    堆栈

     四、生产者和消费者模型

      模型指的概念

        生产者消费者可以实现程序的解耦  

    from multiprocessing import Process,Queue
    import time,random,os
    
    def producer(q):
        for i in range(10):
            res="包子 %s"%i
            time.sleep((random.randint(1,3)))
            q.put(res)
            print("%s生产了%s"%(os.getpid(),res))
    
    def consumer(q):
        while True:
            res=q.get()
            print("%s 吃 %s"%(os.getpid(),res))
            time.sleep((random.randint(2,3)))
    
    if __name__=="__main__":
        q=Queue()
        p=Process(target=producer,args=(q,))
        c=Process(target=consumer,args=(q,))
        p.start()
        c.start()
        print("")
    
    from multiprocessing import Process,Queue
    import time,random,os
    def procducer(q):
        for i in range(10):
            res="包子%s"%i
            time.sleep(0.5)
            q.put(res)
            print("%s生产了%s"%(os.getpid(),res))
    生产者和消费者 1

     线程要不要用生产者消费者模型

       也要用队列来实现

    from multiprocessing import Process,Queue
    import time,random,os
    def procducer(q):
        for i in range(10):
            res="包子%s"%i
            time.sleep(0.5)
            q.put(res)
            print("%s生产了%s"%(os.getpid(),res))
    
    def consumer(q):
        while True:
            res=q.get()
            if res is None:
                break
            print("%s 吃 %s"%(os.getpid(),res))
            time.sleep(random.randint(2,3))
    
    if __name__=="__main__":
        q=Queue()
        p=Process(target=procducer,args=(q,))
        c=Process(target=consumer,args=(q,))
    
        p.start()
        c.start()
    
        p.join()
        q.put(None)
        print("")
    生产者消费者模型
  • 相关阅读:
    git变慢的原因
    MongoDB存储过程创建和使用一例
    关于小游戏的槛和限制
    【转载】如何查看本机电脑的公网IP
    【转载】C#如何获取DataTable中某列的数据类型
    【转载】C#的DataTable使用NewRow方法创建新表格行
    【转载】如何删除Windows远程桌面保存的账号密码数据
    【转载】 C#中ArrayList使用GetRange方法获取某一段集合数据
    【转载】 C#中常见的泛型集合类有哪些
    【转载】C#中使用Insert方法往ArrayList集合指定索引位置插入新数据
  • 原文地址:https://www.cnblogs.com/number1994/p/8185408.html
Copyright © 2011-2022 走看看