Python课程设计 第 38 / 52 篇
进程并发-参考答案
写一个模拟100个用户抢10张火车票的程序,要求如下:
1 100个用户一定是并发查看票数余量,购票当然也是并发执行的
2 用户在购票时模拟网络延迟,可能查票的时候有票,但是购票的时候就没有了
3 进程之间的通信使用硬盘来完成
4 不能出现数据错误,比如多个用户买同一张票,购票成功却票数没减
5 不需要写用户的登录注册
import json
import time
import random
import os
from multiprocessing import Process, Lock
mutex = Lock()
# 互斥锁vs join的区别二:
# 互斥锁可以让一部分代码(修改共享数据的代码)串行,而join只能将代码整体串行
def check():
time.sleep(random.randint(1, 3))
with open('db.json', 'r', encoding='utf-8') as f:
dic = json.load(f)
print('%s 剩余票数:%s' % (os.getpid(), dic['count']))
def pay():
with open('db.json', 'r', encoding='utf-8') as f:
dic = json.load(f)
if dic['count'] > 0:
dic['count'] -= 1
time.sleep(random.randint(1, 3))
with open('db.json', 'w', encoding='utf-8') as f:
json.dump(dic, f)
print('%s 购票成功' % os.getpid())
def task(lock):
check()
lock.acquire()
pay()
lock.release()
if __name__ == '__main__':
for i in range(100):
p = Process(target=task, args=(mutex,))
p.start()
- 基于网络通信写一个用户注册的程序,要求如下:
1 用户在客户端注册时,服务器会给用户的客户端发送一个随机验证码,用户使用它校验。
2 多个用户并发执行注册功能时服务端使用消息队列来处理用户请求
# 生产者消费者模型
import time
import random
import socket
from multiprocessing import Process, JoinableQueue
client = socket.socket()
client.connect(('127.0.0.1', 8099))
def consumer(name, q):
"""
客户端是消费者,客户端发送验证码请求,并输入验证码
:param name:
:param q:
:return:
"""
while True:
res = q.get()
if res is None:
break
time.sleep(random.randint(1, 3))
print('\033[46m消费者===》%s 使用了 %s\033[0m' % (name, res))
q.task_done()
def producer(name, q, food):
"""
服务端是生产者,服务端接收验证码请求,并发送验证码
:param name:
:param q:
:param food:
:return:
"""
for i in range(5):
time.sleep(random.randint(1, 2))
res = '%s%s' % (food, i)
q.put(res)
print('\033[45m生产者者===》%s 生产了 %s\033[0m' % (name, res))
def recv_code():
client.send('code'.encode('utf-8'))
code = client.recv(1024).decode('utf-8')
return code
if __name__ == '__main__':
q = JoinableQueue()
p1 = Process(target=producer, args=('1号服务器', q, recv_code()))
p2 = Process(target=producer, args=('2号服务器', q, recv_code()))
p3 = Process(target=producer, args=('3号服务器', q, recv_code()))
c1 = Process(target=consumer, args=('悟空的客户端', q))
c2 = Process(target=consumer, args=('八戒的客户端', q))
c1.daemon = True # 子进程变成守护进程
c2.daemon = True
p1.start()
p2.start()
p3.start()
c1.start()
c2.start()
# 确定生产者确实生产完毕
p1.join()
p1.join()
p1.join()
# 生产者生产完毕之后,拿到队列中肯定有还有数据,直到这个数据量变为0,q.join()这行代码才算是运行完毕
q.join()
# q.join()一旦结束就意味着队列确实为空,消费者已经确实把数据都取干净了。
print('主进程结束')
# 验证码服务
import socket
import random
server = socket.socket()
server.bind(('127.0.0.1', 8099))
server.listen(5)
while True:
conn, client = server.accept()
print(client)
while True: # 通信循环
try:
msg = conn.recv(1024)
print('客户端的消息: ', msg)
code = ''
for _ in range(4):
code += str(random.randint(0, 9))
conn.send(code.encode('utf-8'))
except Exception:
break
conn.close()
server.close()