zoukankan      html  css  js  c++  java
  • day34 python学习 守护进程,线程,互斥锁,信号量,生产者消费者模型,

    六 守护线程 

    无论是进程还是线程,都遵循:守护xxx会等待主xxx运行完毕后被销毁

    需要强调的是:运行完毕并非终止运行

    #1.对主进程来说,运行完毕指的是主进程代码运行完毕
    
    #2.对主线程来说,运行完毕指的是主线程所在的进程内所有非守护线程统统运行完毕,主线程才算运行完毕

    详细解释:

    #1 主进程在其代码结束后就已经算运行完毕了(守护进程在此时就被回收),然后主进程会一直等非守护的子进程都运行完毕后回收子进程的资源(否则会产生僵尸进程),才会结束,
    
    #2 主线程在其他非守护线程运行完毕后才算运行完毕(守护线程在此时就被回收)。因为主线程的结束意味着进程的结束,进程整体的资源都将被回收,
    而进程必须保证非守护线程都运行完毕后才能结束。

    守护进程的应用场景

    #     举例说明守护进程的应用场景:
    #         假设有两个任务要干,要玩出并发的效果,使用进程的话可以让主进程
    #         执行一个任务,然后开启一个子进程执行一个任务。
    #
    #         如果这两个任务毫无关系,那么就像上面这么做就可以
    #         如果主进程的任务在执行完毕后,子进程的任务没有存在的意义了
    #         那么该子进程应该在开启之前就被设置成守护进程

    例子

    #守护进程的例子
    from multiprocessing import Process
    import os,time,random
    def task():
        print('%s is runing'%(os.getpid(),))
        time.sleep(2)
        print('%s is done'%(os.getpid()))
    def func():
        print('%s is runing'%(os.getpid(),))
        time.sleep(2)
        print('%s is done'%(os.getpid()))
    if __name__ == '__main__':
        p1=Process(target=task,)
        p2 = Process(target=func,)
        p1.daemon=True #1、必须在p.start()之前 2:守护进程不能开启子进程
        p1.start()
        p2.start()
        print('zhu')
        #结果如下,可以看到被守护的进程没有执行出,因为主进程中的代码执行完了
        # ,所以被守护的进程被回收了,然而主进程等到非守护进程则继续执行完毕,才会结束进程
        """zhu
    10024 is runing
    10024 is done"""
    #守护线程的例子
    from threading import Thread
    import os,time,random
    def task():
        print('%s is run'%(os.getpid(),))
        time.sleep(2)
        print('%s is do'%(os.getpid()))
    def func():
        print('%s is runing'%(os.getpid(),))
        time.sleep(1)
        print('%s is done'%(os.getpid()))
    if __name__ == '__main__':
        p1=Thread(target=task,)
        p2 = Thread(target=func,)
        p1.daemon=True #1、必须在p.start()之前
        p1.start()
        p2.start()
        print('zhu')
        #结果如下,守护线程等所有的非守护线程结束才结束才结束
    # 11432 is run
    # 11432 is runing
    # zhu
    # 11432 is done
    守护线程
    #迷惑人的例子迷惑人的例子
    #主进程代码运行完毕,守护进程就会结束
    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也执行了,但是随即被终止
    #打印结果如下,先打印   main   没有打印P1中的内容,因为主进程中的代码执行完了,所以守护进程就终止了
    """main-------
    456
    end456"""
    
    #
    迷惑人的例子
    迷惑人的例子迷惑人的例子
    #主线程
    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=Thread(target=foo)
        p2 = Thread(target=bar)
    
        p1.daemon=True
        p1.start()
        p2.start()
        print("main-------") #守护线程中主线程会等非守护线程执行完毕才完毕,
        # 所以守护线程会等主线程完毕才停止执行,看到结果如下
    """123
    456
    main-------
    end123
    end456"""
    迷惑人的例子,守护线程

    互斥锁

    锁通常被用来实现对共享资源的同步访问。为每一个共享资源创建一个Lock对象,当你需要访问该资源时,调用acquire方法来获取锁对象(如果其它线程已经获得了该锁,则当前线程需等待其被释放),待资源访问完后,再调用release方法释放锁:

    from multiprocessing import Process,Lock
    import time,random,os
    def task(mutex):
        #两种使用互斥锁的方式,方式一
        # mutex.acquire()#  得到锁对象#其他的进程起来之后没有互斥锁对像,然后再这儿等着
        # print('%s is runing'%(os.getpid()))
        # time.sleep(random.randint(1,3))
        # print('%s is run' % (os.getpid()))
        # time.sleep(random.randint(1, 3))
        # print('%s is done' % (os.getpid()))
        # time.sleep(random.randint(1, 3))
        # mutex.release() #释放锁对象,下一个进程获取互斥锁对象,其他的进程执行了
        # # ,但是还是在等着抢锁对象
        #方式二
        with mutex:
            print('%s is runing'%(os.getpid()))
            time.sleep(random.randint(1,3))
            print('%s is run' % (os.getpid()))
            time.sleep(random.randint(1, 3))
            print('%s is done' % (os.getpid()))
            time.sleep(random.randint(1, 3))
    if __name__ == '__main__':
        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()
        print('')
        #打印结果如下,# 而且非 join的那种类型的,join是等上一个进程结束后在开启另一个进程
        #而互斥锁是所有程序都起来了,但是有的在运行,有的在等待锁对象被释出来
      """主
    9200 is runing
    9200 is run
    9200 is done
    6940 is runing
    6940 is run
    6940 is done
    8024 is runing
    8024 is run
    8024 is done
    """
    from multiprocessing import Process,Lock
    import json,time,os,random
    def search():
        with open('file','r',encoding='utf-8') as f:
            dic=json.load(f)
        print('%s还剩%s张票'%(os.getpid(),dic['dirct']))
        time.sleep(random.randint(1,3))#在这里sleep可以判断手速跟网速,(即是点购买的速度)
    def get():
        with open('file','r',encoding='utf-8')as open_f:
            dic=json.load(open_f)
        if dic['dirct']>0:
        #    time.sleep(random.randint(1,3))  #
            with open('file','w',encoding='utf-8') as ge_f:
                dic['dirct']-=1
                json.dump(dic,ge_f)
                print('%s购票成功'%(os.getpid()))
    def func(mutex):
        search() #查票操作,这个是非需要枷锁的过程,所以U谁都可以查询
        with mutex: #但是购买操作,谁抢到锁,谁买到票
            get()
        # mutex.acquire()#两种枷锁方式
        # get()
        # mutex.release()
    
    if __name__ == '__main__':
        mutex=Lock()
    
        for i in range(20):
            p1 = Process(target=func, args=(mutex,))#创建对象要在循环中,
            # 否则就会走一遍就不再下一次了,
            p1.start()
            #p1.join()#不用join,否则就相当与串行的去执行了
        print('zhu')
    
     #这里要记住用json的读取文件中的字典的时候,文件中字典要写成双引号的形式{"dirct": 0}
    抢票程序,经典的LOck

    互斥锁与join的区别:

    # 而且非 join的那种类型的,join是等上一个进程结束后在开启另一个进程
    #而互斥锁是所有程序都起来了,但是有的在运行,有的在等待锁对象被释出来,其他未抢到锁的进程继续抢锁
    #进程池是从始至终都是在执行四个进程,而信号量是有100个任务的话就一下子开启100个任务
    #但是只有10个抢到了锁,然后执行锁里边的内容在执行中,
    from multiprocessing import Process,Semaphore
    import time,os,random
    def task(sm):
        print(os.getpid())#  没有抢到锁的进程并发在执行这个代码
        with sm:
            print('%s 上厕所'%(os.getpid()))
            time.sleep(random.randint(1,3))
    
    if __name__ == '__main__':
        sm=Semaphore(3)
        for i in range(10):
            p=Process(target=task,args=(sm,))#有10个进程在运行,在抢锁呢,抢到的执行锁里边的内容
            # 这就是与进程池的不同
            p.start()
    信号量

    信号量: 也是锁的概念(锁的数量是多把 而lock只有一把锁)

    就是一个公司100个人在用电脑工作,但是公司只有10个打印机当要打印的时候就会抢打印机资源,其他时候正常工作,

    
    
    #进程池是从始至终都是在执行四个进程,而信号量是有100个任务的话就一下子开启100个任务
    #但是只有10个抢到了锁,然后执行锁里边的内容在执行中,
    from multiprocessing import Process,Semaphore
    import time,os,random
    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):
            p=Process(target=task,args=(sm,))#有10个进程在运行,在抢锁呢,抢到的执行锁里边的内容
            # 这就是与进程池的不同
            p.start()
          

    队列  Queue

    平常引用队列  import  queue

    进程 queue 线程queue 引用方式  from mulitprocessing import Queue 

    from multiprocessing import Queue  #进程队列
    q=Queue(3)  #设置队列的容量,也可以不设置
    q.put(1)
    q.put({'ss':1})
    # q.put('sss')
    # q.put([1,2,3])  #当放入的数据数量大于容量时,程序就会卡在这里,
    print(q.get())
    print(q.get())
    print(q.get())  #当往外取得次数大于队列内部的数量,就会卡在这里一直往外取东西
    # ,程序就会卡在这里,

    堆栈

    #堆栈
    import queue
    q=queue.LifoQueue(3)  #先进后出
    q.put({'a':1})
    q.put('xxxxx')
    q.put(3)
    # q.put(4)
    
    print(q.get())
    print(q.get())
    print(q.get())
    print(q.get())
    堆栈,先进后出

    优先级队列

    #优先级队列
    import queue
    q=queue.PriorityQueue(3)
    q.put((10,{'a':1})) #设置优先级,-1  为被取出优先级最高的
    q.put((-1,'xxxxx'))  
    q.put((0,3))
    # q.put(4)
    
    print(q.get())
    print(q.get())
    print(q.get())
    print(q.get())
    设置取出的优先级

    生产者消费者模型*****

    使用队列  实现解耦

    from multiprocessing import Process,Queue
    import time,os
    def procducer(q):
        for i in range(10):
            res='baozi%s'%i
            time.sleep(0.5)
            q.put(res)
            print('%s 生产了%s'%(os.getpid(),i))
    
    def consumer(q):
        while True:
            res=q.get()
            if res==None:  #队列中取到None的时候就是队列中没有内容了,停止!
                break
            print('%s 吃 %s'%(os.getpid(),res))
            time.sleep(2)
    
    
    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)  #将None放入队列中,作为消费者停止从队列中往外取内容的标志
        print('zhu')
    #升级版,
    from  multiprocessing import Process,Queue,JoinableQueue
    import  os,time,random
    def productor(name,q):
        for i in range(3):
            res='%s %s'%(name,i)
            q.put(res)
            print('%s生产了%s %s'%(os.getpid(),name,i))
            time.sleep(0.1)
    
    def consumer(q):
        while True:
            res=q.get()
            if res==None:
                break
            print('%s 吃了 %s'%(os.getpid(),res))
            time.sleep(random.randint(1,3))
    
    if __name__ == '__main__':
        q=Queue()
        p1=Process(target=productor,args=('包子',q,))
        p2 = Process(target=productor, args=('泔水', q,))
        p3 = Process(target=productor, args=('狗粮', q,))
        c1=Process(target=consumer,args=(q,))
        c2=Process(target=consumer,args=(q,))
        p1.start()
        p2.start()
        p3.start()
        c1.start()
        c2.start()
        p1.join()
        p2.join()
        p3.join()
        q.put(None)  #有两个消费者就要用两个None 让消费之吃到None 时结束进程
        q.put(None) 
        print('zhu')
    
    #使用JoinableQueue
    from  multiprocessing import Process,Queue,JoinableQueue
    import  os,time,random
    def productor(name,q):
        for i in range(3):
            res='%s %s'%(name,i)
            q.put(res)
            print('%s生产了%s %s'%(os.getpid(),name,i))
            time.sleep(0.1)
    
    def consumer(q):
        while True:
            res=q.get()
            if res==None:
                break
            print('%s 吃了 %s'%(os.getpid(),res))
            time.sleep(random.randint(1,3))
    
    if __name__ == '__main__':
        q=JoinableQueue()
        p1=Process(target=productor,args=('包子',q,))
        p2 = Process(target=productor, args=('泔水', q,))
        p3 = Process(target=productor, args=('狗粮', q,))
        c1=Process(target=consumer,args=(q,))
        c2=Process(target=consumer,args=(q,))
        p1.start()
        p2.start()
        p3.start()
        c1.daemon=True  #这样设置可以让消费者成为守护进程,
        # 当主进程结束之后就可以让子进程(消费者)结束
        c2.daemon=True
        c1.start()
        c2.start()
        p1.join()
        p2.join()
        p3.join()
        print('zhu')
    生产者消费者升级版
      



  • 相关阅读:
    HTTP协议
    网络编程笔记
    基于udp协议实现QQ:可以并发一对多
    基于udp协议通信:实现了并发
    基于tcp协议通信,运用socketserver模块实现并发
    @PathVariable 与@RequestParam
    IDEA 中的一些概念变化
    Bubble Cup 11
    ACM超时问题
    D
  • 原文地址:https://www.cnblogs.com/wangkun122/p/7978889.html
Copyright © 2011-2022 走看看