进程锁

# 进程锁
    # 多个进程都操作一个数据时(下面指的是文件)、会存在数据安全问题,则需要加入锁

# 先说一个现象
    # 买火车票
        # 当我们手机软件买票时,发现有余票20张,但是点击订票后,告诉你票订光了
        # 这是因为买票时,肯定是一个并发的过程,好多人同时来买票,并发的过程
        # 当一个人订票后,我们后台肯定要修改票数,肯定是修改数据库中的剩余票数

# import json
# import time
# from multiprocessing import Process
#
# def show():
#     '''
#     @funcation功能:模拟查询余票
#                    显示余票
#     :return:
#     '''
#     with open('ticket', mode='r') as f: # ticket文件中的内容是{"ticket":1}这个,模拟存储的票数
#         dic = json.load(f)
#     print('余票:%s' % dic['ticket'])
#
# def buy_ticket(i):
#     '''
#     @funcation功能:模拟买票
#     @param 表示谁来买票
#     :return:
#     '''
#     with open('ticket') as f:
#         dic = json.load(f)
#         time.sleep(0.1) # 模拟网络延时
#
#     if dic['ticket'] >= 1:   # 有余票
#         dic['ticket'] -= 1  # 买一张票后,就减一张票
#         print('\033[32m %d 买到票了\033[0m' % i)
#     else:   # 没有余票了
#         print('\033[31m %d 没买到票\033[0m' % i)
#
#     time.sleep(0.1) # 模拟网络延时
#     with open('ticket', mode='w') as f:
#         json.dumps(dic, f)  # 将在内存中改写的余票数,写入到文件中,模拟写入数据库的过程
#
# if __name__ == '__main__':
#     # 创建5个进程,都绑定的查询余票为子进程,模拟5个人查票,此时5个人都看到有1张票
#     for i in range(5):
#         p = Process(target=show)
#         p.start()
#
#     # 5个人看到有1张票后,则都去点击买票,此时5个人都显示买到票了,也可能多个人显示买票成功了,这是有问题的,因为只有1一张票,确多个人显示买成功了
#     for i in range(5):
#         p = Process(target=buy_ticket, args=(i,))
#         p.start()


# 解决上面举的5个人查看余票都剩1张时,5个人都去点击买票,结果系统显示多个人买票成功的问题,可以用进程锁
    # 上面的问题由于操作文件的相关代码被多个人(进程)操作,
        # 如果多个进程同时都去读那个文件,就会同时读到剩一张票,点击买票时,同样的多个进程同时都去加载那个文件中的剩余票数,
        # 多个进程都发现有余票1张,所以多个进程就认为有余票,就买了,然后将票数减1后,多个进程又同时将余票数写入到了文件中
    # 解决上面的问题思路是,每个进程不能随便的就去读那个文件与写那个文件,而是需要拿到一个锁的钥匙后才能去操作那个文件,锁和钥匙只有一个
        # 当一个进程需要操作那个文件后,则拿到那个钥匙,开了锁后,进入到抽象中的屋子中,则用钥匙关闭了门,然后开始操作文件。
        # 此时如果有另一个进程也要进这个屋子的时候,则必须等待前面那个人操作完了文件后,将门打开并将钥匙归还,后面的人才能操作那个文件
        # 这就是进程锁的概念

import json
import time
from multiprocessing import Process
from multiprocessing import Lock    # 导入进程锁模块

def show():
    '''
    @funcation功能:模拟查询余票
                   显示余票
    :return:
    '''
    with open('ticket', mode='r') as f: # ticket文件中的内容是{"ticket":1}这个,模拟存储的票数
        dic = json.load(f)
    print('余票:%s' % dic['ticket'])

def buy_ticket(i, lock):
    '''
    @funcation功能:模拟买票
    @:param 表示谁来买票
    @:param  接收锁对象的参数
    @:return:
    '''
    lock.acquire()  # 如果钥匙被归还了,则拿到钥匙开锁向下执行,如果钥匙没有被归还,则阻塞在这里,等待锁被归还。  上锁
    with open('ticket') as f:
        dic = json.load(f)
        time.sleep(0.1) # 模拟网络延时

    if dic['ticket'] > 0:   # 有余票
        dic['ticket'] -= 1  # 买一张票后,就减一张票
        print('\033[32m %s 买到票了\033[0m' % i)
    else:   # 没有余票了
        print('\033[31m %s 没买到票\033[0m' % i)

    time.sleep(0.1) # 模拟网络延时
    with open('ticket', mode='w') as f:
        json.dump(dic, f)  # 将在内存中改写的余票数,写入到文件中,模拟写入数据库的过程
    lock.release()  # 归还钥匙      解锁

if __name__ == '__main__':
    # 创建5个进程,都绑定的查询余票为子进程,模拟5个人查票,此时5个人都看到有1张票
    for i in range(5):
        p = Process(target=show)
        p.start()

    lock = Lock()   # 得到一个锁对象
    # 5个人看到有1张票后,则都去点击买票,此时每个进程都会先判断锁有没有被解开后再去买票,如果锁是上锁的则阻塞等待,先拿到钥匙的进程先买
    for i in range(5):
        p = Process(target=buy_ticket, args=(i, lock))  # 将锁传进去
        p.start()

 

转载于:https://www.cnblogs.com/whylinux/p/9807267.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值