进程的实现以及常用方法教程
进程的简介
进程的本质也是程序,而且是正在运行的程序
进程在运行过程中有三种状态,分别是就绪态、运行态以及阻塞态
进程可以分为四种,分别为同步阻塞、同步非阻塞、异步阻塞以及异步非阻塞。
同步是指一个任务的运行需要等待上一个任务的结束;异步是指将一个任务交给操作系统后继续去干其它的事,当该任务结束运行得到结果时只需告知一声即可。
阻塞是指等待其它任务结束或者在原地等待结果;非阻塞是指无序等待,当得到结果后通知一下即可。
在程序运行中,异步非阻塞效率最高。
一、进程的实现方法
1、直接调用Process模块
import time
from multiprocessing import Process
# 第一种:调用Process模块
def func(name):
print("%s 启动了"%name)
time.sleep(0.2)
print("%s 结束了"%name)
if __name__ == '__main__':
p = Process(target=func,args=("egon",))
p.start()
print("猪")
2、写一个类继承Process,调用内中的run方法
import time
from multiprocessing import Process
# 第二种:继承Process模块,调用内中的run方法
class MyProcess(Process):
def __init__(self, name):
super().__init__()
self.name = name
def run(self):
print("%s 启动了" % self.name)
time.sleep(0.2)
print("%s 结束了" % self.name)
if __name__ == '__main__':
p = MyProcess("egon")
p.start()
print("猪")
二、join方法
子进程是由父进程开启的,父进程告诉操作系统创建一个子进程后就继续运行父进程的代码,父进程的代码可能会先运行完然后等待
子进程运行结束,为了保证每个子进程运行完后父进程再运行结束,可以在告知操作系统创建子进程之后调用join方法,保证创建每个子进程后
等待每个子进程的结束再运行并结束父进程。
同时开启了多个子进程的时候,可以每开启一个子进程的时候将其添加到一个列表中,添加完毕后再通过另一个for循环
将每个子进程取出,调用join方法。
join方法要等每个所有子进程都被告知给操作系统之后使用。
import time
from multiprocessing import Process
def func(i):
print("%s 启动了"%i)
time.sleep(i)
print("%s 结束了"%i)
lis = []
if __name__ == '__main__':
for i in range(10):
p = Process(target=func,args=(i,))
p.start()
lis.append(p)
for p in lis:
p.join()
print("猪")
三、每个进程中的数据
每一个进程间的数据是不能直接共用的,每个进程的数据都是独立的。
即使时子进程和父进程的数据也是相互独立的。
原因:每个进程再运行的时候,操作系统会给每个进程再内存中分配一块内存空间,也就导致了每个进程中的数据时相互独立的。
from multiprocessing import Process
import time
money = 100
def test():
global money
money = 99999999
if __name__ == '__main__':
p = Process(target=test)
p.start()
p.join()
print(money)
四、进程相关的方法
current_process().pid:当前进程的PID
getpid():获取当前进程的PID
getppid():获取当前进程的父进程的PID
import time
import os
from multiprocessing import Process
def fun(name):
print("%s 开始运行!"%name, os.getpid(),os.getppid()) # 第一个是子进程的端口号,第二个是父进程的端口号,实际上是每个进程所在的python解释器的端口号
time.sleep(0.2)
print("%s 结束运行!"%name, os.getpid(),os.getppid())
if __name__ == '__main__':
p = Process(target=fun,args=("egon",))
p.start()
print("猪",os.getpid(),os.getppid()) # 第一个是运行父进程的python解释器的端口号,第二个是运行解释器的pycharm编辑器的端口号
五、守护进程
守护进程顾名思义是为了保护某个进程的运行而被创建的。
当被保护的进程死亡时,守护进程也会随之死亡。
守护进程的设定应该在告诉操作系统创建该进程之前。
import time
from multiprocessing import Process
def func(name):
print("%s 正在运行" % name)
time.sleep(0.2)
print("%s 陪葬" % name)
if __name__ == '__main__':
p = Process(target=func,args=("egon",))
p.daemon = True
p.start()
time.sleep(0.2)
print("jason驾崩了!")
time.sleep(1)
六、守护进程
当多个进程去访问同一个数据的时候,可以同时被多个进程拿到。
当每个进程对拿到的数据进行修改操作并保存到原来的位置的时候,一般情况下每个进程都会认为是自己对该数据做了操作。
但实际上每个进程的处理结果都会被下一个进程的处理结果覆盖,导致每个进程得到的反馈是都不正确。
此时需要一个机制,对每个进程处理数据的操作进行限制,在同一时间只有一个进程对该数据进行操作,等待上一个进程处理完后下一个进程才能对数据进行处理。
该机制就是互斥锁,给需要的数据在处理阶段进行上锁操作,每个进程需要拿到钥匙才能对数据进行操作,操作完毕后释放钥匙,下一个进程拿到钥匙后进行数据处理的操作。
PS:钥匙应该只提供一个
1 import time
2 from multiprocessing import Process,Lock
3 import json
4
5
6 def search(i):
7 with open("data.txt","r",encoding="utf-8") as f:
8 data = f.read()
9 dic = json.loads(data)
10 num = dic.get("ticket")
11 print("%s查询:还剩%s张票"%(i,num))
12
13 def buy(i):
14 with open("data.txt","r",encoding="utf-8") as f:
15 data = f.read()
16 dic = json.loads(data)
17 num = dic.get("ticket")
18 time.sleep(0.2) # 模拟网络延迟
19 if num == 0:
20 print("没票了")
21 return
22 num -= 1
23 dic["ticket"] = num
24 with open("data.txt","w",encoding="utf-8") as a:
25 json.dump(dic,a)
26 print("%s抢票成功"%i)
27
28 def run(*args):
29 i,l = args
30 search(i)
31 l.acquire()
32 buy(i)
33 l.release()
34
35 if __name__ == '__main__':
36 l = Lock()
37 for i in range(10):
38 p = Process(target=run,args=(i,l),)
39 p.start()
40 print("zhu")
41
42 """
43 0查询:还剩1张票
44 1查询:还剩1张票
45 2查询:还剩1张票
46 3查询:还剩1张票
47 4查询:还剩1张票
48 5查询:还剩1张票
49 7查询:还剩1张票
50 6查询:还剩1张票
51 8查询:还剩1张票
52 9查询:还剩1张票
53 0抢票成功
54 没票了
55 没票了
56 没票了
57 没票了
58 没票了
59 没票了
60 没票了
61 没票了
62 没票了
63 """
加了互斥锁
1 import time
2 from multiprocessing import Process,Lock
3 import json
4
5
6 def search(i):
7 with open("data.txt","r",encoding="utf-8") as f:
8 data = f.read()
9 dic = json.loads(data)
10 num = dic.get("ticket")
11 print("%s查询:还剩%s张票"%(i,num))
12
13 def buy(i):
14 with open("data.txt","r",encoding="utf-8") as f:
15 data = f.read()
16 dic = json.loads(data)
17 num = dic.get("ticket")
18 time.sleep(0.2) # 模拟网络延迟
19 if num == 0:
20 print("没票了")
21 return
22 num -= 1
23 dic["ticket"] = num
24 with open("data.txt","w",encoding="utf-8") as a:
25 json.dump(dic,a)
26 print("%s抢票成功"%i)
27
28 def run(*args):
29 i,l = args
30 search(i)
31 # l.acquire()
32 buy(i)
33 # l.release()
34
35 if __name__ == '__main__':
36 l = Lock()
37 for i in range(10):
38 p = Process(target=run,args=(i,l),)
39 p.start()
40 print("zhu")
41 """
42 0查询:还剩1张票
43 1查询:还剩1张票
44 3查询:还剩1张票
45 2查询:还剩1张票
46 4查询:还剩1张票
47 5查询:还剩1张票
48 6查询:还剩1张票
49 7查询:还剩1张票
50 8查询:还剩1张票
51 9查询:还剩1张票
52 0抢票成功
53 1抢票成功
54 3抢票成功
55 2抢票成功
56 4抢票成功
57 5抢票成功
58 6抢票成功
59 7抢票成功
60 8抢票成功
61 9抢票成功
62 """
没加锁