守护进程,互斥锁

守护进程

在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()
posted @ 2019-07-03 22:49  abcde_12345  阅读(163)  评论(0编辑  收藏  举报