二十七、多进程,互斥锁
一、创建进程
创建进程就是在内存中重新开辟一块内存空间
将允许产生的代码丢进去
一个进程对应在内存就是一块独立的内存空间,和其他之间没有任何关系,变量也是独立的
进程与进程之间数据是隔离的 无法直接交互
但是可以通过某些技术实现间接交互
"""
如果调用函数,势必会同步等待时间结束完,才会执行其他代码,这里就是多进程同时执行,无需等待。 os.getpid() 显示进程数
os.getppid()) # 查询当前进程的父进程是谁
主程序和子程序在异步过程中,是随机运行的
两种方式:
1.第一种:
from multiprocessing import Process import time import os def test(name): print('%s is running' % name, os.getpid()) print('子进程父进程:', os.getppid()) time.sleep(3) print('%s is over' % name, os.getpid()) print('子进程父进程:', os.getppid()) """ windows创建进程会将代码以模块的方式 从上往下执行一遍 linux会直接将代码完完整整的拷贝一份 windows创建进程一定要在if __name__ == '__main__':代码块内创建 否则报错 """ if __name__ == '__main__': p = Process(target=test, args=('子进程:',)) # 注册 创建一个进程对象 p是一个进程对象 p.start() # 告诉操作系统帮你开启子进程, print('父进程:', os.getpid()) # 查询当前进程数字 print('父进程父进程:', os.getppid()) # 查询当前进程的父进程是谁
2.第二方法:
import os from multiprocessing import Process class MyProcess(Process): def __init__(self, arg1, arg2): super().__init__() #初始化到父类,下面是派生属性 self.arg1 = arg1 self.arg2 = arg2 def run(self): print(self.arg1,self.arg2) print(self.pid) # 等同于os.getpid() print(self.name) print("子进程:", os.getpid()) if __name__ == '__main__': # print("主进程:", os.getpid()) p1 = MyProcess(1,2) p1.start() p2 = MyProcess(3,4) p2.start() print("主进程:", os.getpid())
二、开启多个字进程,p.join()使用方法
join():
主进程代码等待子进程运行结束
p.join()上面是异步执行(子程序),下面是同步执行(主程序),没有p.join()都是异步
from multiprocessing import Process import time
def test(name, i): print('%s is running' % name) time.sleep(i) print('%s is over' % name) if __name__ == '__main__': p_list = [] for i in range(3): p = Process(target=test,args=('进程%s'%i,i)) p.start() p_list.append(p) [p.join() for p in p_list]
# start_time =time.time() # p = Process(target=test, args=('egon', 1)) # p1 = Process(target=test, args=('kevin', 2)) # p2 = Process(target=test, args=('jason', 3)) # p.start() # 仅仅是告诉操作系统帮你创建一个进程 至于这个进程什么时候创 操作系统随机决定 # p1.start() # p2.start() # p2.join() # p.join() # p1.join() # 主进程代码等待子进程运行结束 才继续运行 # p.join() # 主进程代码等待子进程运行结束 print('主') print(time.time() - start_time)
三、进程与进程之间隔离
进程与进程之间是相互隔离,都是独立的一块内存空间,数据不共享
from multiprocessing import Process money = 100 def test(): global money money = 99999999 if __name__ == '__main__': p = Process(target=test) p.start() p.join() print(money) #100
四、守护进程
把子进程改为守护进程,在start()上面添加p.daemon,子进程会随着主进程的结束而结束
def test(name): while True: print('%s总管正常活着' % name) time.sleep(3) print('%s总管正常死亡' % name) if __name__ == '__main__': p = Process(target=test, args=('egon',)) p.daemon = True # 将该进程设置为守护进程 这一句话必须放在start语句之前 否则报错 p.start() i = 0 while i < 10: time.sleep(0.1) print('皇帝jason寿正终寝') i += 1 # 随着主进程的结束而结束
五、互斥锁
from multiprocessing import Process, Lock import time import json # 查票 def search(i): with open('data', 'r', encoding='utf-8') as f: data = f.read() t_d = json.loads(data) print('用户%s查询余票为:%s' % (i, t_d.get('ticket'))) # 买票 def buy(i): with open('data', 'r', encoding='utf-8') as f: data = f.read() t_d = json.loads(data) time.sleep(1) if t_d.get('ticket') > 0: # 票数减一 t_d['ticket'] -= 1 # 更新票数 with open('data', 'w', encoding='utf-8') as f: json.dump(t_d, f) print('用户%s抢票成功' % i) else: print('没票了') def run(i, mutex): search(i) mutex.acquire() # 抢锁 只要有人抢到了锁 其他人必须等待该人释放锁 buy(i) mutex.release() # 释放锁 if __name__ == '__main__': mutex = Lock() # 生成了一把锁 for i in range(10): p = Process(target=run, args=(i, mutex)) p.start()
六、死锁(递归锁)
死锁:同一段代码,如果出现两把或两把以上锁就会出现 死锁 (多进程和多线程都会出现)
from threading import Lock, Thread import time noodle_lock = Lock() fork_lock = Lock() def eat1(name): noodle_lock.acquire() print("%s拿到面条啦!" % name) fork_lock.acquire() print("%s拿到叉子了" % name) print("%s可以吃面楼!" % name) fork_lock.release() noodle_lock.release() def eat2(name): fork_lock.acquire() print("%s拿到叉子了2" % name) time.sleep(1) noodle_lock.acquire() print("%s拿到面条啦2!" % name) print("%s可以吃面楼2!" % name) noodle_lock.release() fork_lock.release() Thread(target=eat1, args=("alex",)).start() Thread(target=eat2, args=("json",)).start() Thread(target=eat1, args=("tank",)).start() Thread(target=eat2, args=("jirry",)).start() # 锁是共通的,两个函数锁相互抢(如果没有阻塞就没问题)
递归锁:Rlock 是一串钥匙,拿到了就可以路通到底
# 锁是唯一的,全局变量 #递归锁:Rlock 是一串钥匙,拿到了就可以路通到底 from threading import RLock, Thread import time fork_lock=noodle_lock = RLock() # RLOCK递归锁,一个钥匙串上两把钥匙 def eat1(name): noodle_lock.acquire() print("%s拿到面条啦!" % name) fork_lock.acquire() print("%s拿到叉子了" % name) print("%s可以吃面楼!" % name) fork_lock.release() noodle_lock.release() def eat2(name): fork_lock.acquire() print("%s拿到叉子了" % name) time.sleep(1) noodle_lock.acquire() print("%s拿到面条啦!" % name) print("%s可以吃面楼!" % name) noodle_lock.release() fork_lock.release() Thread(target=eat1, args=("alex",)).start() Thread(target=eat2, args=("json",)).start() Thread(target=eat1, args=("tank",)).start() Thread(target=eat2, args=("jirry",)).start()