python之路---并发编程之进程&互斥锁

互斥锁

将多个任务对修改共享数据的操作由并发变为“串行”

没有互斥锁的情况下

# json文件
{"count": 2}

# 执行文件
import os
import time
import json
import random
from multiprocessing import Process


def check():
    with open("a.json","r",encoding="utf-8") as f:
        data_dic = json.load(f)
    time.sleep(random.random())
    print('[%s] 在%s 查看了车票,车票还剩:%s' %
          (os.getpid(), time.strftime('%Y-%m-%d %X'), data_dic['count']))


def pay():
    with open("a.json","r",encoding="utf-8") as f:
        data_dic = json.load(f)
    time.sleep(random.random())
    if data_dic['count'] > 0:
        data_dic['count'] -= 1
        time.sleep(random.random())
        with open("a.json","w",encoding="utf-8") as f:
            json.dump(data_dic,f)
        print('[%s] 在%s 购买了车票' % (os.getpid(), time.strftime('%Y-%m-%d %X')))
    else:
        print('[%s] 在%s 购票失败' % (os.getpid(), time.strftime('%Y-%m-%d %X')))


def buy_tickets():
    check()
    pay()


if __name__ == '__main__':
    for i in range(8):
        p = Process(target=buy_tickets)
        p.start()

发现,两张票被8个人购买

有互斥锁的情况下

# json 文件
{"count": 2}

# 执行文件
import os
import time
import json
import random
from multiprocessing import Process, Lock


def check():
    with open("a.json", "r", encoding="utf-8") as f:
        data_dic = json.load(f)
    time.sleep(random.random())
    print('[%s] 在%s 查看了车票,车票还剩:%s' %
          (os.getpid(), time.strftime('%Y-%m-%d %X'), data_dic['count']))


def pay():
    with open("a.json", "r", encoding="utf-8") as f:
        data_dic = json.load(f)
    time.sleep(random.random())
    if data_dic['count'] > 0:
        data_dic['count'] -= 1
        time.sleep(random.random())
        with open("a.json", "w", encoding="utf-8") as f:
            json.dump(data_dic, f)
        print('[%s] 在%s 购买了车票' % (os.getpid(), time.strftime('%Y-%m-%d %X')))
    else:
        print('[%s] 在%s 购票失败' % (os.getpid(), time.strftime('%Y-%m-%d %X')))


def buy_tickets(lock):
    # 如果将锁加到这里,就将整个任务串行了
    check()
    lock.acquire()  # 该进程拿到锁,其余没有锁的进程等待
    pay()
    lock.release()  # 释放锁,其余等待进程竞争

    '''
    或者使用with上下文管理
    with lock:
        pay()
    '''


if __name__ == '__main__':
    mutex = Lock()  # 获得锁对象
    for i in range(8):
        p = Process(target=buy_tickets, args=(mutex,))
        # p = Process(target=buy_tickets, kwargs={'lock': mutex})
        p.start()

总结

1.多个任务并发的去操作共享数据会造成数据错乱,使用互斥锁,虽然使任务对共享数据的操作由并发变为“串行”,减低了效率,但是提高了数据的安全性

2.此方法的共享数据效率低(数据来自于硬盘) 并且需要自己去处理锁的问题

所以,为了解决第二个问题,就要寻求一种方法---->使多个进程共享一个内存空间中的共享数据,该方法可以替我们处理好锁的问题

IPC通信

管道与队列

扫描二维码关注公众号,回复: 3159524 查看本文章

管道与队列将数据存放于内存中,而且队列是通过管道+锁实现的

猜你喜欢

转载自blog.csdn.net/ltfdsy/article/details/82424423