1. 程式人生 > >python全棧開發day32-進程創建,進程同步,進程間的通信,進程池

python全棧開發day32-進程創建,進程同步,進程間的通信,進程池

效果 lose 安全 tip ket eve light spl port

一、內容總結

  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-進程創建,進程同步,進程間的通信,進程池