python全棧開發day32-進程創建,進程同步,進程間的通信,進程池
一、內容總結
1.進程創建
1) Process:兩種創建一個新進程的方法:
1.實例化Process,通過args=(,)元組形式傳參,2創建類繼承Process,類初始化的時候傳參數
2) p.join(),阻塞主進程,執行完p進程後,釋放
3) 守護進程 ,守護主程序代碼執行完畢,p.daemon = True
import time from multiprocessing import Process def func(): while True: print(‘is alive‘) time.sleep(守護進程代碼0.5) def wahaha(): i = 0 while i < 5: print(‘第%s秒‘%i) time.sleep(1) i += 1 if __name__ == ‘__main__‘: p2 = Process(target=wahaha) p2.start() p1 = Process(target=func) p1.daemon = True # 設置p1為守護進程 p1.start() time.sleep(3) print(‘主進程‘) p2.join()# 守護進程會等待子進程結束後才結束守護
4) p.terminate() 不會立即結束,會等待主進程回收資源等
# python和進程
# multiprocessing模塊
# 主進程
# 父子進程
# 父進程需要等待子進程執行結束之後才結束
# 負責回收子進程的一些資源
# 進程與進程之間數據隔離
# 子進程可以在創建之初接收參數
# 但是不能直接返回值
# 異步 父子進程之間的工作是互不幹擾的
# 開啟一個子進程
# multiprocessing.Process
# 第一種方式
# 實例化創建一個進程
# start開啟一個進程
# 第二種方式
# 采用面向對象的形式來創建進程
# 繼承Process
# 在init處傳參數
# 重寫run方法
# 子進程的控制
# join
2.進程的同步
1)、鎖 Lock
加鎖,維護了數據的安全,但降低了程序的效率,但所有的效率都必須建立在數據安全的基礎上;
但凡涉及到並發編程我們都要考慮共享數據的安全性,我需要在並發部分對數據操作格外小心,
如果涉及到數據的不安全就要加鎖控制。
# 查票的例子 import os,time from multiprocessing import Lock,Process import json def search(i): with open(‘db‘) as f: ticket_count = json.load(f) print(‘%s查到了還剩余:%s張余票!‘ % (i,ticket_count[‘count‘])) def buy(i): with open(‘db‘) as f: ticket_count = json.load(f) time.sleep(0.2) # 模擬請求數據庫數據網絡傳輸時延 if ticket_count[‘count‘] > 0: ticket_count[‘count‘] -= 1 print(‘%s號買到了車票!‘% i) time.sleep(0.2) # # 模擬寫入數據庫數據網絡傳輸時延 with open(‘db‘, ‘w‘) as f: json.dump(ticket_count, f) def get_ticket(lock, i): search(i) with lock: buy(i) # 兩種加鎖方式 # # def get_ticket(lock, i): # search(i) # 查票不用加鎖,都可以查 # lock.acquire() # buy(i) # 買票加鎖 # lock.release() if __name__ == ‘__main__‘: lock = Lock() for i in range(10): p = Process(target=get_ticket,args=(lock,i)) p.start()查車票的例子
lock內部實現進程間的通信,使得誰acquire了鎖,誰realease了在多個擁有lock參數子進程中透明。
2)、信號量 Semaphore 鎖+計數器
# 4人KTV的例子 # def ktv(sema,i): # sema.acquire() # print(‘%s 走進ktv!‘ % i) # time.sleep(random.randint(1,5)) # print(‘%s 走出KTV!!!‘% i) # sema.release() def ktv(sema,i): with sema: print(‘%s 走進ktv!‘ % i) time.sleep(random.randint(1,5)) print(‘%s 走出KTV!!!‘% i) if __name__ == ‘__main__‘: sema = Semaphore(4) for i in range(10): p = Process(target=ktv, args=(sema, i)) p.start()4人KTV的例子
3)、事件Event
控制子進程阻塞還是執行的一個機制:
wait方法:
如果is_set() 標誌位為False,則阻塞 wait(n)可以設置阻塞n秒後繼續執行,但標誌位不會改變,還是False
如果is_set() 標誌位為True,效果相當於pass
控制標誌:
is_set():判斷標誌位狀態
set():設置標誌位為True
clear():設置標誌位False
import time, random from multiprocessing import Process,Event e = Event() # print(e.is_set()) 會打印12次,數數吧哈哈 def traffic_light(e): print(‘\033[1;31m紅燈亮了\033[0m‘) while True: time.sleep(2) if e.is_set(): print(‘\033[1;31m紅燈亮了\033[0m‘) e.clear() else: print(‘\033[1;32m綠燈亮了\033[0m‘) e.set() def car(e, i): if not e.is_set(): print(‘car%s 在等待紅燈‘ % i) e.wait() print(‘car%s 通過‘ % i) if __name__ == ‘__main__‘: e = Event() traffic_light1 = Process(target=traffic_light, args=(e,)) traffic_light1.daemon = True traffic_light1.start() li = [] for i in range(10): p = Process(target=car, args=(e, i)) p.start() li.append(p) time.sleep(random.randint(0, 3)) for p in li: p.join() print(‘主程序結束!‘)事件紅綠燈的例子
3.進程間的通信
1.隊列Queue
# IPC 進程之間的通信
empty():# 多進程的情況下 不準:
full():# 多進程的情況下 不準:
put():#隊列慢 會引起程序的阻塞:
get():#隊列空 會引起程序的阻塞:
put_nowait(): # 不會阻塞,但容易丟失數據
get_nowait():# 不會阻塞,但滿的話會報錯
from multiprocessing import Process,Queue def num(q,i): q.put({i:i**i}) if __name__ == ‘__main__‘: q = Queue() for i in range(10): p = Process(target=num, args=(q,i)) p.start() for j in range(10): print(q.get())利用Queue進行進程通信的例子
2.管道
3.Manager
4.進程池
pool
二、預習和擴展
python全棧開發day32-進程創建,進程同步,進程間的通信,進程池