PYTHON多進(jìn)程多線程

目錄
  1.進(jìn)程和線程
      1.1系統(tǒng)多任務(wù)機(jī)制
      1.2進(jìn)程惦界、線程和協(xié)程
          1.2.1進(jìn)程(process)
          1.2.2線程(thread)
          1.2.3串行倾芝、并行论衍、并發(fā)
  2.多線程編程
      2.1PYTHON中的多線程
          2.1.1threading模塊屬性和方法
          2.1.2thread類型屬性和方法
      2.2函數(shù)式開發(fā)實(shí)現(xiàn)
          2.2.1 線程狀態(tài)——join
          2.2.2  線程狀態(tài)——daemon
          2.2.3  線程管理——鎖【Lock/Rlock】
          2.2.4 線程管理——死鎖【Dead Lock】
          2.2.5  線程管理——實(shí)踐【Event】
          2.2.6   油條的故事——Event實(shí)現(xiàn)
          2.2.7 線程管理——條件【Condition】
          2.2.8  生產(chǎn)者消費(fèi)者問題——Condition實(shí)現(xiàn)
          2.2.9  線程管理——隊(duì)列【Queue】
          2.2.10  生產(chǎn)者消費(fèi)者問題——Queue隊(duì)列實(shí)現(xiàn)
          2.2.11 線程管理——其他
       2.3  面向?qū)ο箝_發(fā)實(shí)現(xiàn)
          2.3.1 面向?qū)ο竽莻€(gè)多線程基本語法
  3.多進(jìn)程編程
      3.1多進(jìn)程概述
      3.2python多進(jìn)程開發(fā)
          3.2.1multiprocessing
          3.2.2多進(jìn)程的基礎(chǔ)操作
          3.2.3 多進(jìn)程面向?qū)ο髮?shí)現(xiàn)
          3.2.4 帶參數(shù)的多進(jìn)程:共享堰燎?獨(dú)占基矮?
          3.2.5 多進(jìn)程的簡(jiǎn)化:內(nèi)置進(jìn)程池
          3.2.6 多個(gè)進(jìn)程通信:multiprocessing.Manager
          3.2.7多個(gè)進(jìn)程通信:multiprocessing.Queue
          3.2.8 多個(gè)進(jìn)程通信:multiprocessing.Pipe

1.進(jìn)程和線程

1.1系統(tǒng)多任務(wù)機(jī)制

多任務(wù)操作機(jī)制的引入主要是在相同的硬件資源下怎么提高任務(wù)處理效率的淆储!多任務(wù)的處理機(jī)制可以在提升任務(wù)處理效率的基礎(chǔ)上,快速提升用戶體驗(yàn)家浇!

我們現(xiàn)實(shí)生活中無時(shí)無刻不在上演著多任務(wù)處理操作方式本砰,聽著音樂瞧著代碼,看著小說吃著大餐等等钢悲,都是多任務(wù)的體現(xiàn)点额,計(jì)算機(jī)在還原生活中功能處理流程的同事青团,也在還原生活中的多任務(wù)操作機(jī)制,計(jì)算機(jī)上的各種編程語言在多任務(wù)處理機(jī)制上都有非常友好的技術(shù)支持和實(shí)現(xiàn)方式

PYTHON本身也支持多任務(wù)處理咖楣,并且提供了如下的操作方式
多線程多任務(wù)處理機(jī)制
多進(jìn)程多任務(wù)處理機(jī)制
協(xié)程多任務(wù)處理機(jī)制

1.2進(jìn)程督笆、線程和協(xié)程
1.2.1 進(jìn)程(process)

進(jìn)程:計(jì)算機(jī)中一個(gè)程序在一個(gè)數(shù)據(jù)集上一次動(dòng)態(tài)執(zhí)行過程,主要包含三部分內(nèi)容
程序:描述進(jìn)程的功能以及處理流程
數(shù)據(jù)集:功能處理過程中需要的資源數(shù)據(jù)
進(jìn)程控制:嚴(yán)格控制進(jìn)程執(zhí)行過程中的各種狀態(tài)
通俗來說诱贿,一個(gè)進(jìn)程就是計(jì)算機(jī)上正在運(yùn)行的一個(gè)程序

一個(gè)軟件程序要運(yùn)行娃肿,需要將軟件依賴的數(shù)據(jù)加載到內(nèi)存中,通過CPU進(jìn)行運(yùn)算并按照程序定義的邏輯結(jié)構(gòu)進(jìn)行流程控制珠十,直到數(shù)據(jù)處理完成后程序退出料扰!
在程序?qū)嶋H執(zhí)行過程中,進(jìn)程只是分配需要的數(shù)據(jù)資源焙蹭,是程序的主題晒杈,在程序運(yùn)行時(shí)真正運(yùn)行的是線程,每個(gè)進(jìn)程至少會(huì)有一個(gè)線程

1.2.2 線程(Thread)

計(jì)算機(jī)中程序運(yùn)行的實(shí)際執(zhí)行者就是線程孔厉,線程又稱為輕量級(jí)進(jìn)程拯钻,是一個(gè)CPU的執(zhí)行單元,每個(gè)進(jìn)程至少會(huì)有一個(gè)主線程用于執(zhí)行程序

線程和進(jìn)程對(duì)比如下:
一個(gè)進(jìn)程可以有多個(gè)進(jìn)程撰豺,但是至少有一個(gè)主線程
一個(gè)線程只能屬于一個(gè)進(jìn)程
一個(gè)進(jìn)程中多個(gè)線程粪般,可以共享進(jìn)程中提供的數(shù)據(jù)
CPU運(yùn)算分配給線程,CPU上執(zhí)行運(yùn)算的是線程
線程是最小的運(yùn)行單元污桦,進(jìn)程是最小的資源管理單元

1.2.3串行亩歹、并行、并發(fā)

串行:就是傳統(tǒng)意義上的同步凡橱、順序的意思小作,按照一定的執(zhí)行步驟順序執(zhí)行每個(gè)環(huán)節(jié)

并行:就是傳統(tǒng)意義上的異步,同時(shí)的意思稼钩,同時(shí)執(zhí)行接收到的多個(gè)任務(wù)

并發(fā):同時(shí)接收到多個(gè)任務(wù)顾稀,同時(shí)執(zhí)行多個(gè)任務(wù),但是具體到某個(gè)時(shí)刻~只是在執(zhí)行一個(gè)任務(wù)变抽,只是在很短時(shí)間內(nèi)在多個(gè)任務(wù)之間切換础拨,模擬形成了多個(gè)任務(wù)同時(shí)執(zhí)行的現(xiàn)象

而大部分計(jì)算機(jī)中的因公用程序的執(zhí)行,一般都是并發(fā)執(zhí)行機(jī)制的多任務(wù)處理機(jī)制

因?yàn)镃PU的核心數(shù)目限制绍载,以前的CPU每個(gè)核心只有一個(gè)獨(dú)立的線程,也就是江湖傳言的單核單線程CPU滔蝉,只能執(zhí)行一個(gè)運(yùn)行線程击儡,為了能讓計(jì)算機(jī)實(shí)現(xiàn)多任務(wù)同時(shí)處理的機(jī)制,計(jì)算機(jī)就給CPU定義了時(shí)間片輪詢機(jī)制蝠引,讓CPU在很短的一個(gè)時(shí)間片執(zhí)行任務(wù)A阳谍,下一個(gè)時(shí)間片執(zhí)行任務(wù)B蛀柴、下一個(gè)時(shí)間片執(zhí)行任務(wù)C。這樣短時(shí)間的切換就會(huì)造成多個(gè)任務(wù)同時(shí)運(yùn)行的表象矫夯!

現(xiàn)在所說的CPU一般都是四核八線程鸽疾,或者或者八核十六線程之類的,其實(shí)就是表示了CPU在同一時(shí)間可以同時(shí)執(zhí)行多少個(gè)線程程序训貌,也就是CPU級(jí)別的多線程運(yùn)行機(jī)制制肮。

但是PYTHON為了保證多任務(wù)機(jī)制下的共享數(shù)據(jù)的安全性和完整性,Cpython官方解釋器內(nèi)置了一個(gè)GIL(Global Interceptor Lock:全局解釋器鎖)递沪,只允許在同一時(shí)間內(nèi)CPU只能執(zhí)行一個(gè)線程豺鼻,所以在PYTHON的官方解釋器下,所謂多線程是多線程并發(fā)機(jī)制并不是多線程并行機(jī)制款慨!

2.多線程編程

在python2中提供了標(biāo)準(zhǔn)模塊thread和threading支持多線程的并發(fā)編程儒飒,但是隨著并發(fā)編程的實(shí)際使用操作過程,thread模塊國(guó)語底層的控制方式對(duì)于并發(fā)編程的新手來說不是很友好檩奠,要求多線程的程序開發(fā)邏輯思維清晰同時(shí)又具備大量開發(fā)經(jīng)驗(yàn)的情況下桩了,可以控制的非常精細(xì)
python3中將thread模塊進(jìn)行了規(guī)范內(nèi)置,更名為_thread埠戳,友好的提醒如果你不是并發(fā)編程的骨灰級(jí)愛好者圣猎,請(qǐng)不要輕易闡釋使用_thread進(jìn)行操作,而胡思推薦使用操作更加靈活使用更加簡(jiǎn)潔的threading模塊進(jìn)行并發(fā)編程的處理乞而。

_thread模塊多線程并發(fā)任務(wù)的簡(jiǎn)單實(shí)現(xiàn)如下:

import  _thread,time

#定義函數(shù)送悔,函數(shù)中執(zhí)行循環(huán)遍歷指定的循環(huán)
def test(num):
    for i in range(num):
        print(_thread.get_ident(),":",i)
        
#通過_thread.start_new_thread()啟動(dòng)兩個(gè)線程,分別執(zhí)行test函數(shù)
_thread_start_new_thread(test,(2,))
_thread_start_new_thread(test,(3,))

#讓主線程休眠3s爪模,等待子線程執(zhí)行結(jié)束
time.sleep(3)

2.1 PYHTON中的多線程

官方推薦的_threading模塊的多線程并發(fā)編程機(jī)制欠啤,結(jié)合是下流行的面向過程、面向獨(dú)享的編程處理模式屋灌,主要有兩種操作方式
(1)函數(shù)式的線程創(chuàng)建方式洁段,適合面向過程程序的并發(fā)編程實(shí)現(xiàn)
(2)面向?qū)ο蟮膭?chuàng)建方式,適合面向?qū)ο蟪绦虻牟l(fā)編程實(shí)現(xiàn)

2.1.1threading模塊的屬性和方法
Thread                                   線程類共郭,用于創(chuàng)建和管理線程
Event                                      事件類祠丝,用于線程同步
Condition                                條件類,用于線程同步
Lock/Rlock                               鎖類除嘹,用于線程同步
Timer                                 延時(shí)線程写半,一批能夠與在一定事件后執(zhí)行一個(gè)函數(shù)
Semaphore/BoundedSemaphore      信號(hào)量類,用于線程同步
active_count()/activeCount()       獲取當(dāng)前alive狀態(tài)的所有線程數(shù)量
current_thread()/currentThread()      獲取當(dāng)期正在執(zhí)行的線程對(duì)象
get_ident()                獲取運(yùn)行中程序當(dāng)前線程的唯一編號(hào)
enumerate()                   獲取所有alive狀態(tài)線程列表
local                                  線程局部數(shù)據(jù)類
stack_size([size])                    獲取線程占用內(nèi)存棧的大小
main_thread                         獲取主線程
2.1.2 Thread 類型屬性和方法
__init__(group,target,name,args,kwargs)       構(gòu)造方法尉咕,創(chuàng)建線程類型
is_alive()/isAlive()               判斷當(dāng)前線程是否alive狀態(tài)
run()                          線程執(zhí)行方法叠蝇,自定義線程必須重寫該函數(shù)
start()                       線程啟動(dòng)方法
join(【timeout = None】)    線程獨(dú)占,等待當(dāng)前線程運(yùn)行結(jié)束或者超時(shí)
ident                     標(biāo)識(shí)當(dāng)前線程的唯一編號(hào)
name                       當(dāng)前線程名稱
daemon                   布爾值年缎,判斷當(dāng)前線程是否守護(hù)線程
2.2 函數(shù)式開發(fā)實(shí)現(xiàn)

通過threading 模塊的Thread函數(shù)們可以實(shí)現(xiàn)多線程程序的運(yùn)行
案例需求:火車站窗口售票
(1)單線程實(shí)現(xiàn)模式:相當(dāng)于只有一個(gè)窗口售票

import time
#總票數(shù)
count = 10

def sale_tickle():
    global count
    while count >0:
        print("售出一張票”悔捶,count)
        count -= 1
        time.sleep(0.5)
     else:
         print("售票結(jié)束铃慷,沒有票了”)
if __name__ == "__main__"
    sale_tickle()

多線程售票:相當(dāng)于多個(gè)窗口同時(shí)售票

import time
#總票數(shù)
count = 10

def sale_tickle():
    global count
    while count >0:
        print("售出一張票”,count)
        count -= 1
        time.sleep(0.5)
     else:
         print("售票結(jié)束蜕该,沒有票了”)
if __name__ == "__main__"
    #定義多個(gè)線程(窗口)
    t1 = threading.Thread(name = "窗口1"犁柜,target = sale_tickle)
     t2 = threading.Thread(name = "窗口2",target = sale_tickle)
     t3 = threading.Thread(name = "窗口3堂淡,target = sale_tickle)
     t4= threading.Thread(name = "窗口4"馋缅,target = sale_tickle)
     t5 = threading.Thread(name = "窗口5",target = sale_tickle)
#啟動(dòng)五個(gè)串口同時(shí)售票
t1.start()
t2.start()
t3.start()
t4.start()
t5.start()
#程序運(yùn)行要比單線程運(yùn)行節(jié)省好幾倍的時(shí)間淤齐,這就是多線程的魅力股囊!
2.2.1線程狀態(tài)_join

join:線程的join狀態(tài)是獨(dú)占模式,當(dāng)前線程獨(dú)占CPU運(yùn)行單元更啄,必須等待當(dāng)前線程執(zhí)行完成或者超時(shí)之后稚疹,才能運(yùn)行其他線程

import time
#總票數(shù)
count = 10

def sale_tickle():
    global count
    while count >0:
        print("售出一張票”,count)
        count -= 1
        time.sleep(0.5)
     else:
         print("售票結(jié)束祭务,沒有票了”)
if __name__ == "__main__"
    #定義多個(gè)線程(窗口)
    t1 = threading.Thread(name = "窗口1"内狗,target = sale_tickle)
     t2 = threading.Thread(name = "窗口2",target = sale_tickle)
     t3 = threading.Thread(name = "窗口3义锥,target = sale_tickle)
     t4= threading.Thread(name = "窗口4"柳沙,target = sale_tickle)
     t5 = threading.Thread(name = "窗口5",target = sale_tickle)
#啟動(dòng)五個(gè)串口同時(shí)售票
t1.start()

#線程t1調(diào)用join拌倍,獨(dú)占模式運(yùn)行赂鲤,等待t1線程運(yùn)行結(jié)束或者超時(shí),才能繼續(xù)運(yùn)行其他線程
t1.join()

t2.start()
t3.start()
t4.start()
t5.start()
#程序運(yùn)行要比單線程運(yùn)行節(jié)省好幾倍的時(shí)間柱恤,這就是多線程的魅力数初!
2.2.2線程狀態(tài)-daemon

線程對(duì)象的daemon屬性用于標(biāo)識(shí)某個(gè)線程是否守護(hù)線程
守護(hù)線程的意義在于~跟主線程之間山無陵天地合,同生共死梗顺,一旦主線程執(zhí)行退出泡孩,無論守護(hù)線程是否執(zhí)行完成,都會(huì)直接退出寺谤!

2.2.3線程管理—鎖【Lock/Rlock】

多線程程序在運(yùn)行過程中仑鸥,由于多個(gè)線程訪問的是同一部分?jǐn)?shù)據(jù),很容易會(huì)造成共享數(shù)據(jù)訪問沖突的現(xiàn)象变屁,如果一旦出現(xiàn)沖突程序就會(huì)出現(xiàn)執(zhí)行結(jié)果不符合期望的結(jié)果

此時(shí)共享數(shù)據(jù)的修改操作眼俊,在多線程的情況下,是需要通過鎖定的方式進(jìn)行獨(dú)占修改的敞贡!就如同入廁一樣泵琳,當(dāng)多個(gè)人[線程】在執(zhí)行程序,修改數(shù)據(jù)【入廁】時(shí)誊役,每個(gè)線程在操作過程中都需要鎖定這一部分?jǐn)?shù)據(jù)【廁所】获列,直到數(shù)據(jù)處理完成之后解鎖,下一個(gè)線程才能進(jìn)行操作
python中提供了兩種線程鎖的操作
(1)同步鎖/互斥鎖:lock
(2)可重用鎖 :Rlock
鎖的操作主要是獲取鎖和釋放鎖兩種
(1)acquire()獲取鎖蛔垢,上鎖击孩,鎖定
(2)release()釋放鎖,開鎖鹏漆,解鎖

2.2.4 線程管理-死鎖【Dead Lock】
線程鎖固然功能強(qiáng)大巩梢,可以管理多個(gè)線程之間的共享數(shù)據(jù)問題, 但是同時(shí)它的強(qiáng)大也帶了了比較糾結(jié)的問題艺玲,需要開發(fā)人員對(duì)于鎖定的數(shù)據(jù)有一個(gè)良好的人認(rèn)知括蝠,否則特別容易造成死鎖的現(xiàn)象,比較著名的哲學(xué)家吃飯問題就是死鎖的典型代表

由于計(jì)算機(jī)運(yùn)算速度較快饭聚,所有有兩種方案可以將問題放大
(1)給執(zhí)行函數(shù)添加休眠時(shí)間
(2)添加線程數(shù)量
死鎖并不是每次都會(huì)出現(xiàn)的忌警,而是程序在執(zhí)行過程中,根據(jù)系統(tǒng)CPU時(shí)間片的切換機(jī)制恰好遇到了重復(fù)上鎖的情況秒梳,就會(huì)死鎖法绵。

實(shí)際項(xiàng)目開發(fā)過程中,一定要注意死鎖情況的影響
這樣的情況可以通過可重用鎖Rlock進(jìn)行鎖定處理

pyhton中的互斥鎖酪碘,只有兩種狀態(tài)朋譬,locked和unlocked,如果一旦重復(fù)上鎖就會(huì)死鎖兴垦,但是可重用所Rlock 徙赢,在鎖定的基礎(chǔ)上提供了一個(gè)計(jì)數(shù)器counter,可以計(jì)算上鎖的次數(shù)然后通過release()解鎖時(shí)就會(huì)重新運(yùn)算計(jì)數(shù)器探越,等待計(jì)數(shù)器清零時(shí)所有鎖全都釋放了狡赐!

2.2.5 線程管理—時(shí)間【Event】

線程鎖解決了多個(gè)線程訪問共享數(shù)據(jù)時(shí)沖突的問題,如果多個(gè)線程之間需要通信應(yīng)該怎么解決呢扶关?此時(shí)就需要用到多個(gè)線程之間的可以用于互相通信的處理對(duì)象了阴汇,該處理對(duì)象必須滿足如下基本條件:
(1)該對(duì)象能同時(shí)被多個(gè)線程訪問
(2)該對(duì)象可以被標(biāo)記不同的狀態(tài)
(3)該對(duì)象可以用于控制線程等待|運(yùn)行之間的切換
pyhton提供了一個(gè)事件對(duì)象Event,可以基本滿足上述條件节槐,完成線程之間的通信

set()              添加一個(gè)標(biāo)記狀態(tài)
isSet()/is_set()       檢查事件對(duì)象是否被標(biāo)記             
clear()               清除標(biāo)記狀態(tài)
wait()              事件對(duì)象操作的當(dāng)前線程等待搀庶,直到該對(duì)象被標(biāo)記狀態(tài)
2.2.6 油條的故事- Event實(shí)現(xiàn)

需求:一個(gè)冬天的早晨,顧客去小攤販那里買油條铜异,由于油條都是現(xiàn)炸哥倔,所以顧客需要等待小攤販生產(chǎn)油條,小攤販生產(chǎn)好油條后顧客可以進(jìn)餐揍庄,結(jié)束后打招呼離開

分析:這里有兩個(gè)線程咆蒿,小攤販線程和顧客線程,顧客線程運(yùn)行開始必須等待,小攤販線程工作生產(chǎn)油條沃测,當(dāng)油條生產(chǎn)之后喚醒顧客線程缭黔,此時(shí)小攤販線程等待,顧客就餐完畢之后準(zhǔn)備離開蒂破,喚醒小攤販結(jié)賬走人馏谨!

兩個(gè)線程的通信:事件對(duì)象:threading.Event
set()添加標(biāo)記
wait()線程等待-如果當(dāng)前事件對(duì)象被標(biāo)記~繼續(xù)運(yùn)行
clear()清除標(biāo)記
import threading,time
#定義事件對(duì)象
event = threading.Event()

def xiao_fan():
    print("XF,炸油條.......")
    time.sleep(2)
    #添加標(biāo)記
    event.set()
    event.clear()
    
    print("XF, 賣油條“)
    
    event.wait()
    print("XF:結(jié)賬完畢,謝謝光臨”)
def gu_ke():
    #線程等待~等待事件對(duì)象被標(biāo)記
    event.wait()
    print("GK:買油條“)
    print("GK:吃油條”)
    time.sleep(2)
if __name__ == "__main__":
    xf = threading.Thread(target = xiao_fan)
    gk = threading.Thread(target = gu_ke)

    xf.start()
    gk.start()
2.2.7 線程管理-條件【Condition】

線程條件Condition對(duì)象附迷,也是多
線程并發(fā)模式下一種線程之間通信的友好支持
在某些情況下惧互,我們需要多個(gè)線程在運(yùn)行過程中根據(jù)實(shí)際操作情況,不同功能的線程在滿足對(duì)應(yīng)的條件時(shí)等待喇伯、啟動(dòng)兩種狀態(tài)之間進(jìn)行切換

如經(jīng)典的線程間通信問題:生產(chǎn)者消費(fèi)者問題
生產(chǎn)者負(fù)責(zé)上生產(chǎn)食物喊儡,將食物存儲(chǔ)在列表中;消費(fèi)者負(fù)責(zé)消費(fèi)稻据,也就是從列表中刪除數(shù)據(jù)艾猜;這里的存儲(chǔ)食物的列表,我們限制了長(zhǎng)度攀甚,最多容納20個(gè)食物數(shù)據(jù)
此時(shí)就會(huì)出現(xiàn)這樣的問題箩朴,如果列表中的食物已經(jīng)達(dá)到20;那么所有的生產(chǎn)者線程不能繼續(xù)生產(chǎn)食物了秋度,必須處于等待狀態(tài)炸庞,等待消費(fèi)者消費(fèi)了食物之后再次生產(chǎn)
同理如果列表中的食物為空了,所有的消費(fèi)者也就不能吃食物了荚斯,必須處于等待狀態(tài)埠居,等待生產(chǎn)者生產(chǎn)了食物之后才能消費(fèi)

Conditon()對(duì)象的屬性和方法
acquire()                                        鎖定
release()                                        解鎖
wait()                                        釋放鎖,同時(shí)阻塞當(dāng)前線程事期,等待被喚醒
wait_for()                            釋放鎖滥壕,同時(shí)阻塞當(dāng)前線程,等待被喚醒
notify()                                      喚醒
notify_all()                            喚醒所有等待condition條件的線程
2.2.8 生產(chǎn)者消費(fèi)者問題-Condition 實(shí)現(xiàn)

需求:生產(chǎn)者消費(fèi)者問題兽泣,描述的是多個(gè)線程之間的通信處理方式和手段绎橘。多個(gè)生產(chǎn)者線程生產(chǎn)食品放到指定的食品容器中,并喚醒所有的消費(fèi)者線程開始就餐如果食品容器容量飽和唠倦,則所有生產(chǎn)者線程等待
多個(gè)消費(fèi)者線程在指定的視屏容器中獲取食物就餐称鳞,并喚醒所有的生產(chǎn)者線程開始生產(chǎn),如果食品容器中沒有任何視屏了稠鼻,則所有消費(fèi)者線程等待

import threading,time,random
#定義食物列表
foods = list()
#創(chuàng)建一個(gè)線程條件對(duì)象
con = threading.Conditon()
def product():
    while True:
        time.sleep(0.5)
        con.acquire()
        if  len(foods)<20:
            _no = random.randint(0,20)
            print("生產(chǎn)者{}生產(chǎn)了:format(threading.current_thread().getName(),_no)
            foods.append(_no)
            print("PRO--",len(foods))
            con.notify()
        else:
            con.wait()
            print("生產(chǎn)者{}----等待”冈止。format(threading.current_thread().getName()))
con.release()

def  consumer():
    while True:
        time.sleep(0.5)
        con.acquire()
        if len(foods) >0:
            _no = foods.pop()
            print("消費(fèi)者{}消費(fèi)了".format(threading.current_thread().getName()), _no)
            print("CUS--", len(foods))       
            con.notify()
        else:
            con.wait()
            print("消費(fèi)者{}-----等待”.format(threading.current_thread().getName()))
         con.release()
if __name__ == "__main__":
    #創(chuàng)建多個(gè)生產(chǎn)者線程
    for i in range(5):
        p = threading.Thread(name = "_p" + str(i),target = product)
        p.start
    #創(chuàng)建多個(gè)消費(fèi)者線程
    for j in range(2):
        c = threading.Thread(name = "_c" + str(j),target = consumer)
        c.start()
2.2.9 線程管理-隊(duì)列【Queue】

多線程并發(fā)編程的重點(diǎn),是線程之間共享數(shù)據(jù)的訪問問題和線程之間的通信問題
為了解決線程之間數(shù)據(jù)共享問題候齿,python提供了一個(gè)數(shù)據(jù)類型【隊(duì)列】可以用于在多線程并發(fā)模式下熙暴,安全的訪問數(shù)據(jù)而不會(huì)造成數(shù)據(jù)共享沖突
pyhton中queue模塊提供的隊(duì)列類型Queue的操作模式如下

put(【timeout = None】) 想隊(duì)列中添加數(shù)據(jù)闺属,隊(duì)列如果滿了,一直阻塞知道超市或者隊(duì)列中有數(shù)據(jù)被刪除之后添加成功
get(【timeout = None】)從隊(duì)列中獲取數(shù)據(jù)周霉,如果隊(duì)列為空掂器,一直阻塞知道超時(shí)或者隊(duì)列中添加數(shù)據(jù)之后獲取成功

2.3面向?qū)ο箝_發(fā)實(shí)現(xiàn)

pyhton人性化的提供了使用與更加強(qiáng)大場(chǎng)合的多線程并發(fā)編程
面向?qū)ο蟮牟僮髂J剑宲ython的多線程并發(fā)更加優(yōu)秀

2.3.1面向?qū)ο蠖嗑€程基本語法

面向?qū)ο蟮亩嗑€程诗眨,主要是讓自定義類型派生自threading.Thread類
重寫Thread類型的run()方法唉匾,然后創(chuàng)建自定義線程類的對(duì)象之后孕讳,調(diào)用start()方法啟動(dòng)

3.多進(jìn)程編程

3.1多進(jìn)程概述

進(jìn)程是正在執(zhí)行中國(guó)的應(yīng)用程序匠楚,一個(gè)進(jìn)程包含了該應(yīng)用程序的所有信息,如加載數(shù)據(jù)內(nèi)存空間厂财、代碼芋簿、程序數(shù)據(jù)、對(duì)象句柄璃饱、執(zhí)行單元等等与斤,一個(gè)應(yīng)用程序根據(jù)其功能的多樣性,可以通過多個(gè)進(jìn)程并發(fā)的形式來實(shí)現(xiàn)

計(jì)算機(jī)中多線程的操作已經(jīng)可以實(shí)現(xiàn)多任務(wù)的處理機(jī)制了荚恶,但是如果實(shí)際到多核CPU或者多個(gè)CPU的硬件主機(jī)撩穿,多進(jìn)程并發(fā)編程的實(shí)現(xiàn)能比多線程并發(fā)機(jī)制更加有效的利用和發(fā)揮硬件資源優(yōu)勢(shì)

3.2pyhton多進(jìn)程開發(fā)

3.2.1multiprocessing

python內(nèi)建標(biāo)準(zhǔn)模塊multiprocessing 對(duì)多進(jìn)程并發(fā)編程提供了良好的支持,通過該模塊的Process進(jìn)程類型谒撼,可以很方便的創(chuàng)建和管理多個(gè)進(jìn)程食寡,通過該模塊提供的Lock|Rlock進(jìn)程鎖類型、Event事件類型廓潜。Condition條件類型等等也可以很方便的完成進(jìn)程間同步操作

和多線程的操作方式類似抵皱,多進(jìn)程的實(shí)現(xiàn)方式也提供了面向過程的實(shí)現(xiàn)和面向?qū)ο蟮膶?shí)現(xiàn),同時(shí)多進(jìn)程的本地?cái)?shù)據(jù)共享和通信模式也非常的類似多線程編程

multiprocessing常見屬性和方法

Process                進(jìn)程類型辩蛋,用于創(chuàng)建和管理進(jìn)程
Lock/Rlock            進(jìn)程互斥鎖/重用鎖呻畸,用于進(jìn)程同步
Event                     進(jìn)程事件類型,用于進(jìn)程同步
Condition               進(jìn)程條件類型悼院,用于進(jìn)程同步
Queue                   進(jìn)程隊(duì)列類型伤为,用于多進(jìn)程數(shù)據(jù)共享
Manager                 進(jìn)程管理類型,用于多進(jìn)程數(shù)據(jù)共享
listener|Client         進(jìn)程監(jiān)聽|客戶端据途,基于網(wǎng)絡(luò)多進(jìn)程之間的數(shù)據(jù)共享
3.2.2多進(jìn)程的基礎(chǔ)操作

main方法運(yùn)行的是主進(jìn)程绞愚,通過multiprocessing創(chuàng)建的子進(jìn)程是由主進(jìn)程產(chǎn)生的!

3.2.3對(duì)進(jìn)程面向?qū)ο髮?shí)現(xiàn)

多進(jìn)程的面向?qū)ο蟮膶?shí)現(xiàn)方式類似多線程的操作模式
自定義進(jìn)程類型昨凡,繼承系統(tǒng)進(jìn)程標(biāo)準(zhǔn)類型multiprocessing.Process
重寫父類的run()方法爽醋,在方法中定義執(zhí)行代碼
在使用時(shí)創(chuàng)建該自定義進(jìn)程類型的對(duì)象,調(diào)用對(duì)象的start()方法啟動(dòng)一個(gè)新的進(jìn)程

3.2.4帶參數(shù)的多進(jìn)程:共享便脊?獨(dú)占蚂四?

多線程的操作模式下我們的全局變量是多個(gè)線程共享的,所以多線程并發(fā)模式下對(duì)于數(shù)據(jù)的修改非常危險(xiǎn),那么多進(jìn)程模式下數(shù)據(jù)的處理應(yīng)該是什么樣的呢遂赠?
通過兩種方式來觀察多進(jìn)程模式下數(shù)據(jù)的處理
(1)全局變量的數(shù)據(jù)
(2)參數(shù)數(shù)據(jù)

3.2.5 多進(jìn)程的簡(jiǎn)化:內(nèi)置進(jìn)程池

多進(jìn)程的操作在實(shí)際應(yīng)用中也是非常多的久妆,但是純底層的代碼開發(fā)控制并發(fā)也是一件非常繁瑣的事情,所以就出現(xiàn)了面向過程多進(jìn)程并發(fā)的優(yōu)化操作方式:進(jìn)程池pool
通過進(jìn)程池pool可以快速創(chuàng)建多個(gè)進(jìn)程執(zhí)行指定函數(shù)跷睦,完成高并發(fā)處理操作
(1)Pool對(duì)象的屬性和方法
apply(func,args) 傳遞參數(shù)args并執(zhí)行函數(shù)func筷弦,同時(shí)阻塞當(dāng)前進(jìn)程知道該函數(shù)執(zhí)行完成,函數(shù)func智慧在進(jìn)程池中的一個(gè)進(jìn)程中運(yùn)行
apply_async(func,args,callback,error_callback)
傳遞參數(shù)args并執(zhí)行函數(shù)func抑诸,該方法不會(huì)形成阻塞烂琴,函數(shù)執(zhí)行完成之后可以通過結(jié)果對(duì)象的get(方法獲取結(jié)果,如果結(jié)果對(duì)象可用是會(huì)自動(dòng)調(diào)用callback指定的函數(shù)蜕乡,如果結(jié)果對(duì)象調(diào)用失敗是會(huì)自動(dòng)調(diào)用error_callback指定的函數(shù)
close() Pool進(jìn)程池的底層工作機(jī)制是向進(jìn)程池提交任務(wù)產(chǎn)生工作進(jìn)程執(zhí)行該方法是主動(dòng)停止給進(jìn)程池提交任務(wù)奸绷,并等待所有提交任務(wù)執(zhí)行完成退出
terminate()立即結(jié)束該進(jìn)程,當(dāng)進(jìn)程池對(duì)象被回收時(shí)自動(dòng)調(diào)用該方法
join()等待工作進(jìn)程退出层玲,再次之間必須調(diào)用close()或者terminate

3.2.6 多個(gè)進(jìn)程通信:multiprocessing.Manager

不同進(jìn)程之間的數(shù)據(jù)通信号醉,涉及到核心的數(shù)據(jù)共享問題,主要由python中提供的內(nèi)建模塊multiprocessing.Manager類型實(shí)現(xiàn)辛块,該類型內(nèi)置了大量的用于數(shù)據(jù)共享的操作

multiprocessing.Manager 常見屬性和方法

Array             內(nèi)置進(jìn)程間共享數(shù)組類型
Queue           內(nèi)置進(jìn)程間共享隊(duì)列類型
list()          內(nèi)置進(jìn)程間共享列表類型
dict()         內(nèi)置進(jìn)程間共享字典類型
Value             內(nèi)置進(jìn)程間共享值類型
Barrier           進(jìn)程同步類型
BoundedSemaphore|Semaphore 進(jìn)程信號(hào)量類型
Lock|Rlock               進(jìn)程互斥鎖/重用鎖
Event                      進(jìn)程同步時(shí)間類型
Conditon                  進(jìn)程同步條件類型
3.2.7 多個(gè)進(jìn)程通信:multiprocessing.Queue

多個(gè)進(jìn)程之間的痛惜操作畔派,數(shù)據(jù)的床底在pyhotn中的multiprocesisng模塊中提供了一個(gè)專門用于多進(jìn)程之間進(jìn)行數(shù)據(jù)傳遞的隊(duì)列:Queue

multiprocessing.Queue常見屬性和方法

put(data【,timeout= None】) 添加一個(gè)數(shù)據(jù)到隊(duì)列中
put_nowait(data)                 添加一個(gè)數(shù)據(jù)到隊(duì)列中润绵,非阻塞模式
get(【timeout = None】) 從隊(duì)列中獲取一個(gè)數(shù)據(jù)
get_nowait()        從隊(duì)列中獲取一個(gè)數(shù)據(jù)线椰,非阻塞模式
full()               判斷隊(duì)列是否已滿
empty()            判斷隊(duì)列是否已空
close()                     關(guān)閉隊(duì)列
qsize()                        獲取隊(duì)列中的元素?cái)?shù)量
3.2.8 多個(gè)進(jìn)程通信:multiprocessing.pipe

python為了更加友好的多個(gè)進(jìn)程之間的數(shù)據(jù)通信操作,提供了一個(gè)管道類型專門用于進(jìn)程之間的協(xié)作:multipricessing.pipe

multiprocessing.pipe 常見屬性和方法

__init__(duplex = True)         初始化方法授药,返回兩個(gè)數(shù)據(jù)conn1,conn2分別表示管道的兩端士嚎,默認(rèn)是雙向通信,如果duplex = False悔叽,  conn1只能接受消息莱衩,  conn2只能發(fā)送消息
send
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市娇澎,隨后出現(xiàn)的幾起案子笨蚁,更是在濱河造成了極大的恐慌,老刑警劉巖趟庄,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件括细,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡戚啥,警方通過查閱死者的電腦和手機(jī)奋单,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來猫十,“玉大人览濒,你說我怎么就攤上這事呆盖。” “怎么了贷笛?”我有些...
    開封第一講書人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵应又,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我乏苦,道長(zhǎng)株扛,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任汇荐,我火速辦了婚禮洞就,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘拢驾。我一直安慰自己奖磁,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開白布繁疤。 她就那樣靜靜地躺著,像睡著了一般秕狰。 火紅的嫁衣襯著肌膚如雪稠腊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,692評(píng)論 1 305
  • 那天鸣哀,我揣著相機(jī)與錄音架忌,去河邊找鬼。 笑死我衬,一個(gè)胖子當(dāng)著我的面吹牛叹放,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播挠羔,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼井仰,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了破加?” 一聲冷哼從身側(cè)響起俱恶,我...
    開封第一講書人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎范舀,沒想到半個(gè)月后合是,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡锭环,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年聪全,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辅辩。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡难礼,死狀恐怖吱七,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鹤竭,我是刑警寧澤踊餐,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站臀稚,受9級(jí)特大地震影響吝岭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜吧寺,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一窜管、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧稚机,春花似錦幕帆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽隧枫。三九已至,卻和暖如春碱茁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背仿贬。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工纽竣, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人茧泪。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓蜓氨,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親队伟。 傳聞我的和親對(duì)象是個(gè)殘疾皇子穴吹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 必備的理論基礎(chǔ) 1.操作系統(tǒng)作用: 隱藏丑陋復(fù)雜的硬件接口,提供良好的抽象接口缰泡。 管理調(diào)度進(jìn)程刀荒,并將多個(gè)進(jìn)程對(duì)硬件...
    drfung閱讀 3,541評(píng)論 0 5
  • 本文是我自己在秋招復(fù)習(xí)時(shí)的讀書筆記,整理的知識(shí)點(diǎn)棘钞,也是為了防止忘記缠借,尊重勞動(dòng)成果,轉(zhuǎn)載注明出處哦宜猜!如果你也喜歡泼返,那...
    波波波先森閱讀 11,268評(píng)論 4 56
  • 又來到了一個(gè)老生常談的問題,應(yīng)用層軟件開發(fā)的程序員要不要了解和深入學(xué)習(xí)操作系統(tǒng)呢姨拥? 今天就這個(gè)問題開始绅喉,來談?wù)劜?..
    tangsl閱讀 4,129評(píng)論 0 23
  • 1.內(nèi)存的頁面置換算法 (1)最佳置換算法(OPT)(理想置換算法):從主存中移出永遠(yuǎn)不再需要的頁面;如無這樣的...
    杰倫哎呦哎呦閱讀 3,254評(píng)論 1 9
  • 楊瀾說過:沒有人有義務(wù)必須透過連你自己都毫不在意的邋遢外表革屠,去發(fā)現(xiàn)你優(yōu)秀的內(nèi)在凿试。 小時(shí)候衣服都是家里給買,或者穿親...
    賣藝的小青年Ace劍心閱讀 241評(píng)論 1 2