進程PID相關
from multiprocessing import Process
import os
def P1():
print("this is a P1")
print("子進程的PID",os.getpid())
print("子進程的父進程的PID",os.getppid()) # 父進程的PID
def P2():
print("this is a P2")
if __name__ == '__main__':
a1 = Process(target=P1,)
a2 = Process(target=P2,name='hahaha') # 指定進程名稱
a1.start()
a2.start()
print(a1.name) # 進程名稱
print(a2.name)
print(a1.pid) # 輸出進程的PID號碼
print(os.getpid()) # 輸出主進程PID
進程其他方法(結束子進程)
import time
from multiprocessing import Process
def P1():
time.sleep(5)
print("process 1")
if __name__ == '__main__':
a1 = Process(target=P1,)
a1.start()
print(a1.is_alive()) # 查看子進程是否還在運行
time.sleep(1)
a1.terminate() # 給系統一個結束子進程的信號 返回 None
time.sleep(1)
print(a1.is_alive())
進程之間的空間隔離
from multiprocessing import Process
import time
num = int(100)
def p1():
global num # 聲明變量,要對函數外部變量進行修改
num = int(10)
print("子進程中:",num)
print('>>',num)
if __name__ == '__main__':
a = Process(target=p1,)
print("=====01")
a.start()
print("=====02")
a.join() #等待子進程運行結束
print("=====03")
print(num)
# 輸出的變量值不同 說明進程之間是隔離運行的
主進程中print 執行兩次問題
python 每次執行都會加載默認main函數 子進程執行時會把主進程中的所有代碼當做main(或模塊)加載一遍.所以會有輸出兩邊
守護進程
# 守護進程 一直在後臺運行 主進程一旦結束了 所有的子進程都要結束
import time
from multiprocessing import Process
def p1():
time.sleep(5)
print("this is a p1")
if __name__ == '__main__':
a = Process(target=p1,)
a.daemon = True # 將該進程設置爲守護進程 必須寫在start 之前 如果主進程結束 那麼子進程也要立即結束
a.start()
print("主進程結束")
主進程結束並不意味這代碼的結束,而其中的普通子進程還在運行 ,daemon 只是將其設爲守護進程,如果主進程結束,那麼守護進程也會結束,但是普通進程還會繼續運行.
殭屍進程和孤兒進程
殭屍進程:子進程比父進程先結束,但是父進程又沒有回收子進程的資源,子進程成爲一個殭屍進程,所以主進程要等待子進程執行結束,回收子進程的資源.
孤兒進程:父進程被殺死了,子進程沒有了父進程,所有進程都在init進程下,孤兒進程將直接被init進程接管回收.
鎖(互斥鎖,進程鎖,同步鎖)
from multiprocessing import Process,Lock
import json
import time
def p(i,lic):
# 加鎖 當所有進程運行到這裏的時候 只有一個能搶到這個鎖 其他的執行到此會進行等待
lic.acquire()
time.sleep(1)
print("%s"%i)
# 解鎖 表示當前結束了 其他的可以繼續來搶了
lic.release()
if __name__ == '__main__':
lic = Lock()
for i in range(10):
a = Process(target=p,args=(i,lic))
a.start()
模擬測試搶票代碼
from multiprocessing import Process,Lock
import json
import time
def show_1(i):
with open ('ticket','r',encoding='utf-8') as f:
ticket_data = f.read()
#print(ticket_data)
#print(eval(ticket_data))
t_data = eval(ticket_data)
#print(t_data,type(t_data))
print('%s查詢剩餘票數:%s'%(i,t_data['count']))
def get_1(i,l1):
# 加鎖
l1.acquire()
print("%s開始!"%i)
with open ('ticket','r',encoding='utf-8') as f:
ticket_data = f.read()
t_data = eval(ticket_data)
if t_data['count'] > 0:
t_data['count'] -= 1
print("%s開始搶票"%i)
time.sleep(0.7)
with open('ticket','w') as w:
w.write(str(t_data))
print("%s搶票成功" % i)
#json.dump(open('ticket','w'),t_data)
else:
print("沒票了")
#解鎖
l1.release()
if __name__ == '__main__':
l1 = Lock()
for i in range(10):
p1 = Process(target=show_1,args=(i,))
#p2 = Process(target=get_1(),)
p1.start()
for i in range(10):
c1 = Process(target=get_1,args=(i,l1))
c1.start()
數據共享
進程之前空間是隔離的,但是有些情況需要多個進程配合,所以設計進程通信
from multiprocessing import Process,Manager,Lock
import time
def f1(md,i,l2):
# 執行到此處都會等待 並行程序再次串行話 雖然降低了效率但是保證了安全
l2.acquire()
print("%s開始!"%i)
#md['name'] += 1
tmp = md['name']
tmp -= 1
time.sleep(1)
md['name'] = int(tmp)
l2.release()
# for 循環創建子進程 並且等待子進程全部執行結束
if __name__ == '__main__':
plist = []
l2 = Lock()
m = Manager()
# 創建了一個manager類型的字典 用於進程通信數據共享
md = m.dict({'name':100})
for i in range(10):
p = Process(target=f1,args=(md,i,l2))
p.start()
plist.append(p)
#[k.join for k in plist]
for k in plist:
k.join()
print(md['name'])