zoukankan      html  css  js  c++  java
  • python进程数据隔离,守护进程,锁,信号量和事件

    主要内容:

    # Process
    # 1.进程之间的数据隔离问题
    # 2.守护进程

    # 几个进程的模型 ---- 进程同步的工具
    # 有先后顺序 就是同步
    # 进程之间 就是异步
    # 希望原本异步的多进程操作,维持一个顺序 -- 同步工具
    # 3.锁 Lock *****
    # 4.信号量 Semaphore ***
    # 5.事件 Event **

    1.进程之间的数据隔离问题

    from multiprocessing import Process
    
    n = 100
    def fun():
        global  n
        n -= 1
        
        return n
    if __name__ == '__main__':
        p = Process(target=fun)
        p.start()
        print(n)
    
    """
    # 进程与进程之间的数据是隔离的
    # 内存空间是不能共享的
    # 所以要想进行通信,必须借助其他手段
    # 且这两个进程都是自愿的
    
    # 子进程的执行结果父进程获取不到
    # 父进程依赖子进程的执行结果呢
    # 父进程如何获取子进程的执行结果???
        # 父子进程之间通过socket通信
    """

    2.守护进程

    # 设置成守护进程之后 会有什么效果呢?
    # 守护进程会在主进程的代码执行完毕之后直接结束,无论守护进程是否执行完毕

    from multiprocessing import Process
    import time
    
    
    def fun():
        print("start")
        time.sleep(3)
        print("这是一个好天气")
    
    if __name__ == '__main__':
        p = Process(target=fun)
        p.daemon = True
        # 守护进程的属性,默认是False,如果设置成True,就表示设置这个子进程为一个守护进程
        # 设置守护进程的操作应该在开启子进程之前
        p.start()
        time.sleep(1)
        print("主进程结束了!")
    
        # 设置成守护进程之后 会有什么效果呢?
        # 守护进程会在主进程的代码执行完毕之后直接结束,无论守护进程是否执行完毕

    关于守护进程的一个需要注意的点,示例如下:(注意下面的fun2里面的in fun2只运行了两次,是跟随主函数的)

    import time
    from multiprocessing import Process
    
    def fun():
        print("start")
        time.sleep(3)
        print("今天天气不错")
    def fun2():
        while True:
            print("in fun2")
            time.sleep(0.5)
    
    if __name__ == '__main__':
        p = Process(target=fun)
        p.start()
        p = Process(target=fun2)
        p.daemon = True
        p.start()
        time.sleep(1)
        print("主程序结束了")
    
    """
    运行结果如下:
    in fun2
    start
    in fun2
    主程序结束了
    今天天气不错
    """

    守扩应用主要有如下功能.:

        # 报活 主进程还活着
        # 100台机器 100个进程  10000进程
        # 应用是否在正常工作 - 任务管理器来查看
        # 守护进程如何向监测机制报活???send/写数据库
        # 为什么要用守护进程来报活呢?为什么不用主进程来工作呢???
            # 守护进程报活几乎不占用CPU,也不需要操作系统去调度
            # 主进程能不能严格的每60s就发送一条信息

    下面是多进程起socket的实例:

    
    
    import socket
    from multiprocessing import Process
    def fun(conn):
    try:
    while 1:
    ret = conn.recv(1024)
    print(ret)
    conn.send(b"hi")
    except ConnectionAbortedError:
    pass
    finally:
    conn.close()
    if __name__ == '__main__':

    sk = socket.socket()
    ip_addr=("127.0.0.1",9000)
    sk.bind(ip_addr)
    sk.listen()
    try:
    while True:
    conn,addr = sk.accept()
    Process(target=fun,args=(conn,)).start()
    finally:
    sk.close()
     

    锁:

    # 锁
    # lock = Lock() # 创造了一把锁
    # lock.acquire() # 获取了这把锁的钥匙
    # lock.release() # 归还这把锁的钥匙

    锁的示例:

    import time,json
    from multiprocessing import Lock
    from multiprocessing import Process
    
    def search(i):
        with open("db","r") as f :content = json.load(f)
        time.sleep(0.2)
        print("第%s个用户正在查看,还剩%s个票"%(i,content["count"]))
    def buy(i):
        with open("db","r") as f :content = json.load(f)
        time.sleep(0.2)
        print("第%s个用户正在查看,还剩%s个票"%(i,content["count"]))
        if content["count"] > 0:
            print("第%s个用户购票成功!"%i)
            content["count"] -= 1
            with open("db","w") as f : json.dump(content,f)
    def test(i,lock):
        search(i)
        lock.acquire()
        buy(i)
        lock.release()
    
    if __name__ == '__main__':
        lock = Lock()
        # lock.acquire()
        # lock.
        for i in range(10):
            Process(target=test,args=(i,lock)).start()

    # 当多个进程共享一段数据的时候,数据会出现不安全的现象,
    # 需要加锁来维护数据的安全性

     信号量

    # 信号量的本质
        # 多把钥匙对应一把锁
        # lock+count计数
    互斥锁同时只允许一个线程更改数据,而信号量Semaphore是同时允许一定数量的线程更改数据 。
    假设商场里有4个迷你唱吧,所以同时可以进去4个人,如果来了第五个人就要在外面等待,等到有人出来才能再进去玩。
    实现:
    信号量同步基于内部计数器,每调用一次acquire(),计数器减1;每调用一次release(),计数器加1.当计数器为0时,acquire()调用被阻塞。这是迪科斯彻(Dijkstra)信号量概念P()和V()的Python实现。信号量同步机制适用于访问像服务器这样的有限资源。
    信号量与进程池的概念很像,但是要区分开,信号量涉及到加锁的概念

    示例代码:

    import os,time,random
    from multiprocessing import Process,Semaphore
    def go_ktv(sem,user):
        sem.acquire()
        print("%s在ktv中" % user)
        time.sleep(random.randint(3,10))
        print("%s走出了ktv"%user)
        sem.release()
    
    if __name__ == '__main__':
        sem = Semaphore(2)
        for i in range(10):
            Process(target=go_ktv,args=(sem,i)).start()
    
    """
    # 信号量的本质
        # 多把钥匙对应一把锁
        # lock+count计数
    """

    事件:

    python线程的事件用于主线程控制其他线程的执行,事件主要提供了三个方法 set、wait、clear。
    
        事件处理的机制:全局定义了一个“Flag”,如果“Flag”值为 False,那么当程序执行 event.wait 方法时就会阻塞,如果“Flag”值为True,那么event.wait 方法时便不再阻塞。
    
    clear:将“Flag”设置为False
    set:将“Flag”设置为True

     示例代码:

    import time
    import random
    from multiprocessing import Process,Event
    def ligth(e):
        print("33[1;31m 红灯亮33[0m")
        while True:
            time.sleep(2)
            if e.is_set():
                print("33[1;31m 红灯亮33[0m")
                e.clear()
            else:
                print("33[1;32m 绿灯亮33[0m")
                e.set()
    
    #车 等或者通过
    def car(id,e):
        if not e.is_set():
            print("car %s等待" %id)
            e.wait()
        print("car %s通过"%id)
    def police_car(id,e):
        if not e.is_set():
            e.wait(timeout=0.5)
        print("police car %s 通过" % id )
    #主进程启动交通控制烦,启动车的进程
    if __name__ == '__main__':
        e = Event()
        Process(target=ligth,args=(e,)).start()
        for i in range(10):
            Process(target=car,args=(i,e)).start()
            time.sleep(random.randrange(0, 3, 2))
  • 相关阅读:
    226_翻转二叉树
    199_二叉树的右视图
    145_二叉树的后序遍历
    做IT,网络/系统/数据库/软件开发都得懂
    [恢]hdu 1200
    [恢]hdu 2080
    [恢]hdu 1222
    [恢]hdu 1128
    [恢]hdu 2153
    [恢]hdu 2132
  • 原文地址:https://www.cnblogs.com/ahliucong/p/9366128.html
Copyright © 2011-2022 走看看