zoukankan      html  css  js  c++  java
  • 守护进程,互斥锁

    守护进程

    在Python中,守护进程也是一个进程,并且只能是子进程守护主进程。

    了解:操作系统级别的守护进程是为了让其他进程不挂,挂了就会重启它。

    默认情况下 主进程即使代码执行完毕了 也会等待子进程结束才会结束自己。

    为了避免孤儿进程的产生,被守护进程(主进程)结束,守护进程(子进程)就结束

    from multiprocessing import Process
    import time
    
    def task():
        print("zi run")
        time.sleep(3)
        print("zi over")
    
    if __name__ == '__main__':
        p = Process(target=task)
        p.daemon = True  # 将这个进程设置为了守护进程  必须在开启进程前设置
        p.start()
        print("主over")
    
    主over	# 主进程结束,子进程就结束
    

    进程安全问题

    当并发的多个任务,要同时操作同一个资源,就会造成数据错乱的问题

    解决方法是,将并发操作公共资源的代码由并发变为串行,牺牲效率,解决安全问题

    解决方案1: join

    直接使用join函数

    但是用join并不完善,因为并不是全部在操作公共资源,并且这样做还不如直接串行,开进程还降低了效率

    ​ 多个进程之间原本公平竞争,现在被join强行规定了顺序

    解决方案2: 互斥锁

    多个进程之间互相排斥的锁

    1. mutex代表互斥锁

    2. 其原理就是将要操作公共资源的代码锁起来 以保证同一时间只能有一个进程在执行这部分代码

    3. 区别在于没有锁的代码,还是可以并发执行

    4. 锁其实只是给执行代码加了限制,本质是一个标志为True或False

    from multiprocessing import Process, Lock
    import time, random
    
    def task1(mutex):
        # 这里的可以并发执行
        for i in range(10000):
            print(1)
    
        mutex.acquire() # 加锁
        time.sleep(random.random())
        print('1111111111')
        time.sleep(random.random())
        print('2222222222')
        mutex.release()	# 解锁
    
    
    def task2(mutex):
        for i in range(10000):
            print(2)
    
        mutex.acquire()
        time.sleep(random.random())
        print(444444444444)
        time.sleep(random.random())
        print(555555555555)
        mutex.release()
    
    
    if __name__ == '__main__':
        mutex = Lock()	# 创建一把互斥锁
        print('创建锁了!!!')
    
        p1 = Process(target=task1, args=(mutex,))
        p2 = Process(target=task2, args=(mutex,))
    
        p1.start()
        p2.start()
    
    未加锁的数字会并发打印,混乱,但是加锁的数据一定是完整打印的
    

    如何使得即保证安全,又提高效率

    锁的 粒度

    粒度指的是被锁住的代码多少,被锁住的代码越多,粒度越高,效率越低

    互斥锁的案例

    • 抢票
    from multiprocessing import Process, Lock
    import json
    
    def show():
        with open('db.json', 'r', encoding='utf-8') as fr:
            data = json.load(fr)
            print('剩余票数', data['count'])
    
    def buy():
        with open('db.json', 'r', encoding='utf-8') as fr:
            data = json.load(fr)
            count = data['count']
    
        if count > 0:
            count -= 1
            data['count'] = count
            with open('db.json', 'w', encoding='utf-8') as fw:
                json.dump(data, fw)
            print('购买成功')
    
    
    def task(mutex):
        show()
        mutex.acquire()
        buy()
        mutex.release()
    
    
    if __name__ == '__main__':
        mutex = Lock()
        for i in range(7):
            p = Process(target=task, args=(mutex,))
            p.start()
    
  • 相关阅读:
    checkpoint出现的时间
    快速断开当前数据库的所有连接的方法
    SQLSERVER备份数据库的时候copy only选项的意思
    SQLSERVER备份事务日志的作用
    SQLSERVER使用密码加密备份文件以防止未经授权还原数据库
    Windows Azure终于到来中国了
    SQLSERVER2005的安装目录结构(下)
    SQLSERVER2005的安装目录结构(上)
    给大家分享两款正在使用的reflector插件
    一套内容采集系统 解放编辑人员
  • 原文地址:https://www.cnblogs.com/lucky75/p/11129607.html
Copyright © 2011-2022 走看看