Day 32 并发编程2
Day 32 并发编程2
守护进程
守护进程由主进程创建,守护进程有一下两个特点:
- 守护进程会在主进程代码执行结束后就结束
- 守护进程内无法再开启子进程
from multiprocessing import Process,Lock
import time
def task1():
print('task start')
time.sleep(10)
print('task end')
if __name__ == '__main__':
p1=Process(target=task1)
p1.daemon=True #表示p1是主进程的守护进程
p1.start()
print('main start')
time.sleep(2)
print('main end')
main start
task start
main end
进程安全问题
当并发的多个任务要同时操作公共资源时,就是造成数据错乱的问题
解决方法就是讲并发操作编程串行操作,但是牺牲了效率,提升了安全性
- 将并行改成串行
from multiprocessing import Process
def task1():
print("-------name is nick")
print("-------gender is girl")
print("-------age is 18")
def task2():
print("++++++++name is bgon")
print("++++++++gender is oldman")
print("++++++++age is 48")
if __name__ == '__main__':
p1 = Process(target=task1)
p2 = Process(target=task2)
p1.start()
p1.join()
p2.start()
- 互斥锁
互斥锁
互斥锁的原理就是将要操作的公共资源锁起来,保证同一时间只能有一个进程在执行这部分代码
什么是互斥锁:
互相排斥的锁
优点:可以将部分代码串行
缺点:必须保证只有一把锁
from multiprocessing import Process,Lock
import time,os
def task1(mutex):
mutex.acquire()
pid=os.getpid()
print(f'task1 start {pid}')
time.sleep(3)
print(f'task1 end {pid}')
mutex.release()
def task2(mutex):
mutex.acquire()
pid=os.getpid()
print(f'task2 start {pid}')
time.sleep(3)
print(f'task2 end {pid}')
mutex.release()
if __name__ == '__main__':
mutex=Lock()
p1 = Process(target=task1, args=(mutex,))
p2 = Process(target=task2, args=(mutex,))
p1.start()
time.sleep(1)
p2.start()
# 先执行完p1 p1解锁后再执行p2
from multiprocessing import Process,Lock
import time,os
def task1(mutex):
# mutex.acquire()
pid=os.getpid()
print(f'task1 start {pid}')
time.sleep(3)
print(f'task1 end {pid}')
# mutex.release()
def task2(mutex):
# mutex.acquire()
pid=os.getpid()
print(f'task2 start {pid}')
time.sleep(3)
print(f'task2 end {pid}')
# mutex.release()
if __name__ == '__main__':
mutex=Lock()
p1 = Process(target=task1, args=(mutex,))
p2 = Process(target=task2, args=(mutex,))
p1.start()
# time.sleep(1)
p2.start()
#上述代码就是并行p1 p2同时start 同时end
案例-抢票
from multiprocessing import Process,Lock
import time,os,json
JSON_PATH='ticket.json'
metux=Lock()
def show():
with open(JSON_PATH,'r') as fr:
data=json.load(fr)
ticket_count=data["count"]
print(ticket_count)
def buy():
with open(JSON_PATH,'r') as fr:
data=json.load(fr)
print(data["count"])
if data["count"]>=1:
data["count"] -= 1
with open(JSON_PATH,'w') as fw:
json.dump(data,fw)
print('抢票成功')
def buy_with_lock(metux):
metux.acquire()
buy()
metux.release()
if __name__ == '__main__':
for i in range (10):
p=Process(target=buy_with_lock,args=(metux,))
p.start()
IPC 队列
ipc指的就是进程间通信
进程间通信几种方式
-
创建一个共享文件
缺点:效率低
优点:理论上交换的数据量非常大
适用于:交互不频繁但是数据量非常大的情况
-
共享内存
缺点:数据量不能太大
优点:效率高
适用于:交互频繁,数据量较小
-
管道
管道也是基于文件的,它是单向的,编程比较复杂
-
socket
编程复杂,更适用于基于网络来交换数据
共享内存的几种方式
-
Manager
可以为我们创建进程间同步的容器,但是没有处理安全问题,所以不常用
-
Queue
翻译为队列,是一种特殊的容易,特点是先进先出
-
栈
栈也是一种特殊的容器,特点是先进后出