锁的概念以及 模拟抢票练习

  一、重要概念

***** 锁:
### 应用场景:*****
    ### 多个进程需要操作同一份数据的时候,会产生数据不安全,应该使用锁,避免多个进程同时修改同一个文件!    
    ### 为保证数据的安全,同一时刻同一段代码,只能由一个进程来执行这段代码。
    ### 多进程中,只有去操作一些进程之间可以共享的数据资源的时候才需要加锁!
    
### 实现方法:
    ## acquire release
    ## 上下文管理:with lock: 
    
### Lock ———— 是一个互斥锁!!!

  二、代码

  推荐利用“上下文管理”的方法加锁:

# -*- coding:utf-8 -*-
import time
import json
from multiprocessing import Process,Lock


def search_tickets(name):
    with open('tickets','r',encoding='utf-8')as f:
        dic = json.load(f)
        print('%s 查看余票还有:%s'%(name,dic['count']))


def buy_ticket(name):
    with open('tickets','r',encoding='utf-8')as f:
        dic = json.load(f)
    # 模拟读票的网络延迟
    time.sleep(0.2)
    if dic['count'] >=1:
        dic['count'] -= 1
        # 模拟买票的延迟
        time.sleep(0.3)
        # 修改文件中的数据
        with open('tickets','w',encoding='utf-8')as f:
            json.dump(dic,f)
            print('%s 成功购买了一张票!'%name)
    else:
        print('余票不足,%s 买票失败'%name)

def buy(name,lock):
    # 查看可以同时进程
    search_tickets(name)
    # 购票需要加锁
    # 推荐上下文管理的方式
    with lock:
        buy_ticket(name)


if __name__ == '__main__':
    # 初始化一个锁对象
    lock = Lock()
    # 开进程
    name_lis = ['wanghw', 'whw', 'www', 'wahaha']
    for name in name_lis:
        process_buy = Process(target=buy,args=(name,lock))
        process_buy.start()

  当然,在buy函数中,不用上下文管理的话,可以这样写:

def use(name,lock):
    # 查票可以是并发的
    search_ticket(name)
    # 手动加锁
    lock.acquire()
    buy_ticket(name)
    lock.release()

  tickets文件中的内容如下(注意,要用json读取的话字典中字符串必须用双引号

{"count": 2}

  效果如下:

 

posted on 2019-04-16 16:21  江湖乄夜雨  阅读(243)  评论(0编辑  收藏  举报