• python 锁


    内容概要

    • 进程对象及其他方法
    • 僵尸进程与孤儿进程
    • 守护进程
    • 互斥锁
    • 队列介绍
    • 进程间通信IPC机制
    • 生产者消费者模型
    • 线程相关知识点

    进程对象及其他方法

    如何查看进程的PID号
    命令法:
    windows: tasklist
             tasklist |findstr PID查看具体的进程
    mac:     进入终端之后输入ps aux
    	     ps aux|grep PID查看具体的进程
    
    用python功能查看:
    
        from multiprocessing import Process,current_process
        pid = current_process().pid  # 查看当前进程的进程号
        p.terminate()   # 杀死当前进程,是告诉操作系统帮你去杀死当前进程 但是需要一定的时间 而代码的运行速度极快
        p.is_alive()     # 判断当前进程是否存活
        
        用OS模块的功能查看:
        import os
        os.getpid()  # 查看当前进程进程号
        os.getppid()  # 查看当前进程的父进程进程号
    
    代码实现:
    
    from multiprocessing import Process,current_process
    import os
    import time
    
    
    def task(name):
        print(f'子进程{name}开始')
        # pid_1 = current_process().pid
        pid_1 = os.getpid()
        pid_2 = os.getppid()
        print(pid_1)
        print(pid_2)
        print(f'子进程运行{name}结束')
    
    
    if __name__ == '__main__':
        # pid = current_process().pid
        pid = os.getpid()
        print(pid,'主')
        p = Process(target=task, args=('1',))
        p.start()
        time.sleep(3)   #  不能刚运行就杀死该程序
        p.terminate()
        time.sleep(2)
        print(p.is_alive())
        
    

    僵尸进程与孤儿进程

    # 僵尸进程
    """
    死了但是没有死透
    当你开设了子进程之后 该进程死后不会立刻释放占用的进程号
    因为子进程要让父进程能够查看到它开设的子进程的一些基本信息 占用的pid号 运行时间
    父进程会回收子进程占用的pid号等,父进程调用join方法等待子进程运行结束
    所有的进程都会步入僵尸进程
    	危险的僵尸进程: 父进程不死并且在无限制的创建子进程并且子进程也不结束
    	
    """
    
    # 孤儿进程
    """
    子进程存活,父进程意外死亡
    操作系统会开设一个“儿童福利院”专门管理孤儿进程回收相关资源
    """
    

    守护进程

    该子进程与主进程同生死,只要主进程结束,该守护进程一定会立即终止
    
    方法:
    p.daemon = True
    注意: 将进程p设置成守护进程  这一句一定要放在start方法上面才有效否则会直接报错
    

    互斥锁

    多个进程操作同一份数据的时候,会出现数据错乱的问题
    针对上述问题,解决方式就是加锁处理:将并发变成串行,牺牲效率但是保证了数据的安全

    用法:
    调用锁类生成互斥对象
    mutex = Lock()

    获得该互斥对象
    mutex.accquire()
    
    释放该互斥对象
    mutex.release()
    

    扩展: 行锁 表锁

    注意:
    1.锁不能轻易的使用,容易造成死锁现象(我们写代码一般不会用到,都是内部封装好的)
    2.锁只在处理数据的部分加来保证数据安全(只在争抢数据的环节加锁处理即可)

    代码实现:

    def run(i, mutex):
        search(i)
        # 给买票环节加锁处理
        # 抢锁
        mutex.acquire()
    
        buy(i) # 操作数据
        # 释放锁
        mutex.release()
    
    
    if __name__ == '__main__':
        # 在主进程中生成一把锁 让所有的子进程抢 谁先抢到谁先买票
        mutex = Lock()
        for i in range(1,11):
            p = Process(target=run, args=(i, mutex))
            p.start()
    
    

    队列介绍

    队列:管道+锁

    管道:subprocess
    stdin stdout stderr

    队列:先进先出
    堆栈:先进后出

    使用方法:

    from multiprocessing import Queue
    # 创建一个队列
    q = Queue  # 括号内可以传数字 标示生成的队列最大可以同时存放的数据量
    # 往队列中存数据,当队列数据放满了之后 如果还有数据要放程序会阻塞 直到有位置让出来 不会报错
    q.put('传的值')
    # 去队列中取数据,队列中如果已经没有数据的话 get方法也会原地等待(阻塞)直到有数据为止
    v = q.get()
    v = q.get_nowait()  # 没有数据直接报错,信息为:queue.Empty
    v = q.get(timeout=3)  # 没有数据之后原地等待三秒之后再报错,信息为:  queue.Empty
    其他方法:
    q.full()  # 判断当前队列是否满了
    q.empty()  # 判断当前队列是否空了
    """
    q.full()
    q.empty()
    q.get_nowait()
    在多进程的情况下是不精确,因为下一瞬间队列可能被其他进程操作了
    """
    

    代码实现:

    from multiprocessing import Queue
    q = Queue(3)
    q.put(1)
    q.put(2)
    q.put(3)
    try:
        print(q.full())
        v_1 = q.get()
        print(v_1)
        v_2 = q.get()
        print(v_2)
        v_3 = q.get()
        print(v_3)
        print(q.empty())
        v_4 = q.get(timeout=3)
        print(v_4)
    except Exception as e:
        print('没有数据了')
    

    IPC机制

    进程间通信或者跨进程通信,是指两个进程之间进行数据交换的过程。
    这里借助队列通信
    使用方法:
    同上

    代码实现:

    from multiprocessing import Queue,Process
    
    
    def producer(q):
        q.put('hello')
    
    
    if __name__ == '__main__':
        q = Queue()
        p = Process(target=(producer), args=(q,))
        p.start()
        res = q.get()
        print(res)
    
    

    生产者消费者模型

    生产者:生产/制造东西的
    消费者:消费/处理东西的
    该模型除了上述两个之外还需要一个媒介就是 队列

    核心思想:
    调用JoinableQueue模块用来计数,将消费者设置成守护进程,当q.join()运行时代表队列的数据已全部被消化,此时关闭主进程.
    该模块功能:每当你往该队列中存入数据的时候 内部会有一个计数器+1,当你调用task_done的时候 计数器-1
    q.join() 当计数器为0的时候 才往后运行

    代码实现:

    from multiprocessing import JoinableQueue,Process
    import random
    import time
    
    
    def producer(x,porducer_name,q,name):
        for i in range(x):
    
            time.sleep(random.randint(1,3))
            q.put(name)
            print(f'{porducer_name}产生数据{name}')
    
    def consumer(q,teacher_name):
        while True:
            time.sleep(random.randint(1,3))
            name=q.get()
            if name:
                print(f'{teacher_name}处理数据{name}')
                q.task_done()
    
    
    
    
    if __name__ == '__main__':
        q = JoinableQueue()
        p2 = Process(target=producer,args=(4,'egon',q,'date'))
        p3 = Process(target=producer,args=(4,'tank',q,'数据'))
        p1 = Process(target=consumer, args=(q,'json'))
        p4 = Process(target=consumer, args=(q,'lili'))
    
        p2.start()
        p3.start()
        p1.daemon = True
        p4.daemon = True
        p4.start()
        p1.start()
        p2.join() # 如果不等这两个产生者,此时队列里没有数据,守护进程直接被干死了
        p3.join() # 如果不等这两个产生者,此时队列里没有数据,守护进程直接被干死了
        q.join()
    
    
  • 相关阅读:
    C#中datagridview单元格值改变实现模糊查找
    C#中建立treeView
    L2008 最长对称子串
    第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(昆明)
    GPLT团体程序设计天梯赛练习集 L1041~L1050
    GPLT团体程序设计天梯赛练习集 L1051~L1060
    GPLT团体程序设计天梯赛练习集 L1061~L1072
    第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(昆明)(热身赛)
    L2007 家庭房产 并查集
    利用反射把查询到的Table、Reader转换成List、Model
  • 原文地址:https://www.cnblogs.com/Franciszw/p/12763994.html
Copyright © 2020-2023  润新知