? from multiprocessing import Lock
? 让并发变成串行,牺牲了执行效率,保证了数据安全。
? 在程序并发执行时,需要修改数据时使用。
模拟抢票实例:
data:
"ticket_num":3
代码:
import json
import time
from multiprocessing import Process
from multiprocessing import Lock
def search(user): # 查看余票功能
with open('data.txt', 'r', encoding='utf8') as f: # 打开数据文件
dic = json.load(f)
print(f'用户{user}查看余票,还剩{dic.get("ticket_num")}张')
def buy(user): # 余票数据修改功能
with open('data.txt', 'r', encoding='utf8')as f: # 再次打开是为了打开最新数据
dic = json.load(f) # 拿到车票相关数据
time.sleep(0.2) # 模拟网络延时
if dic.get("ticket_num") > 0: # 还有余票就购票,余票数量减1
dic['ticket_num'] -= 1
with open('data.txt', 'w', encoding='utf8')as f:
json.dump(dic, f) # 保存车票相关数据
print(f'用户:{user}抢票成功!')
else:
print(f'用户:{user}抢票失败!')
def run(user, mutex): # 抢票功能
search(user) # 调用查看余票功能
mutex.acquire() # 加锁
buy(user) # 抢票功能
mutex.release() # 解锁
if __name__ == '__main__':
mutex = Lock() # 调用Lock()得到一个锁对象
for i in range(10): # 设置10个用户来同时抢票
# 调用Process得到一个p对象
p = Process(target=run, args=(f'用户{i}', mutex))
p.start() # 创建子进程
? 相当于内存中产生一个队列空间,可以存放多个数据,但数据的顺序是由先进的排在前面
from multiprocessing import Queue
# 调用队列类,实例化队列对象 q
q = Queue(5) # 若传参队列中可以存放5个数据
# q1 = Queue() # 若不传参,队列中可以存放无限大的数据,前提硬件能更得上
# put添加数据,若队列中的数据满了,则卡住
q.put(1)
# 查看队列是否满了
print(q.full()) # True
# 添加数据,若队列满了,则会报错
q.put_nowait(6)
# q.get(): 获取的数据遵循 "先进先出",若队列中无数据可取,也会卡住
print(q.get())
get_nowait: # 获取数据,队列中若没有,则会报错
print(q.get_nowait())
# 判断队列是否为空
print(q.empty()) # False
? 进程间数据时相互隔离的,若想实现进程间通信,可以利用队列
from multiprocessing import Process
from multiprocessing import Queue
def test1(q):
data = 'test1'
q.put(data)
print('进程1开始添加数据')
def test2(q):
data = q.get()
print(f'进程2开始读取数据{data}')
if __name__ == '__main__':
q = Queue()
p1 = Process(target=test1, args=(q, ))
p2 = Process(target=test2, args=(q, ))
p1.start()
p2.start()
print('主进程')
生产者和消费者:
? 生产者生产数据,消费者使用数据
? 程序中:通过队列,生产者把数据添加到队列中,消费者从队列中获取数据
实例:
from multiprocessing import Queue, Process
import time
def producer(name, food, q):
for i in range(5):
data = food, i
msg = f'用户{name}开始制作{data}'
print(msg)
q.put(data)
time.sleep(0.2)
def consumer(name, q):
while True:
data = q.get()
if not data:
break
print(f'用户{name}开始吃{data}')
if __name__ == '__main__':
q = Queue()
p1 = Process(target=producer, args=('json', '油条', q))
p2 = Process(target=producer, args=('allen', '红烧肉', q))
c1 = Process(target=consumer, args=('jack', q))
c2 = Process(target=consumer, args=('wills', q))
p1.start()
p2.start()
c1.daemon = True
c2.daemon = True
c1.start()
c2.start()
p2.join()
print('主进程')
? 线程与进程都是虚拟单位,目的是为了更好地描述事物
? 进程是资源单位
? 线程是执行单位
? 开启一个进程,一定会产生一个线程,线程才是真正的执行者
? 节省内存资源
? 开启进程:
? 1、开辟一个名称空间,每开启一个进程都会占用一份内存资源
? 2、会自动生成一个线程
? 开启线程:
? 1、一个进程可以开启多个线程
? 2、线程的开销远小于进程
? 注意:进程可以实现并行,线程不能实现并行,线程只能实现并发,
? 线程之间的数据是共享的
from threading import Thread
import time
def task():
print('线程开启')
time.sleep(1)
print('线程结束')
if __name__ == '__main__':
t = Thread(target=task)
t.start()
from threading import Thread
import time
class MyThread(Thread):
def run(self):
print('线程开启')
time.sleep(1)
print('线程结束')
if __name__ == '__main__':
t = MyThread()
t.start()
from threading import Thread, Lock
mutex = Lock()
mutex.acquire() # 上锁
······
mutex.release() # 解锁
原文:https://www.cnblogs.com/allenchen168/p/11723043.html