例1:
10个人去买票,先去查询余票,有票就去购买。代码如下:
# ticket.py {"ticket": 1} # 只有一张票
import json import time from multiprocessing import Process from multiprocessing import Lock def show(i): # 查询票 with open('ticket') as f: # 读取文件 dic = json.load(f) print('余票:%s'%dic['ticket']) # 余票,所以人都能查到票 def buy_ticket(i): # 买票,这个代买只有一张票,但是所有人都能买,但是打印发现好几个人买到票了,几个人没买到票。这不符合需求,因为在一个进程买票后,去修改票数时,由于时间太快,没来得及修改,就回到是其他进程买到票。 with open('ticket') as f: # 读票数 dic = json.load(f) time.sleep(0.1) if dic['ticket'] > 0: # 判断条件 dic['ticket'] -= 1 # 票数减1 print('%s号买到票了'%i) else: print('%s号没买到票'%i) time.sleep(0.1) with open('ticket', 'w') as f: # 将减1后的票数写入到文件 json.dump(dic, f) if __name__ == '__main__': for i in range(10): # 生成10个进程 p = Process(target=show, args=(i,)) # 查询票 p.start() lock = Lock() for i in range(10): p = Process(target=buy_ticket, args=(i,)) # 买票 p.start()
解决办法:加锁
好比一个上锁的房间,门口只有一个钥匙,一个线程拿到钥匙进去修改数据没出来前,其他进程只能等着。
import json import time from multiprocessing import Process from multiprocessing import Lock # 加锁 def show(i): with open('ticket') as f: dic = json.load(f) print('余票:%s'%dic['ticket']) def buy_ticket(i, lock): # 接收锁 lock.acquire() # 拿钥匙进门 with open('ticket') as f: dic = json.load(f) time.sleep(0.1) if dic['ticket'] > 0: dic['ticket'] -= 1 print('%s号买到票了'%i) else: print('%s号没买到票'%i) time.sleep(0.1) with open('ticket', 'w') as f: json.dump(dic, f) lock.release() # 还钥匙 if __name__ == '__main__': for i in range(10): p = Process(target=show, args=(i,)) p.start() lock = Lock() # 实例化 for i in range(10): p = Process(target=buy_ticket, args=(i,lock)) # 传入锁 p.start()
这样会出现有几张票就只有几个人能买票了,数据就安全了。