多進程和多線程

多進程:


多任務(wù):

簡單的說就是操作系統(tǒng)(os)可以同時運行多個任務(wù)休弃。我們的操作系統(tǒng)就是多任務(wù)玫芦。

單核cpu:

? ? ? ? ? ? ? ? ? ? ? 1桥帆、時間片輪換 :每個進程被分配一個時間? ? ? ? ? ?段慎皱,稱作它的時間片茫多,即該進程允許運行的時間

? ? ? ? ? ? ? ? ? ? 2、優(yōu)先級別調(diào)度:優(yōu)先級別越高就約會被優(yōu)先調(diào)用

多核cpu:??


1跪帝、并發(fā)? ?:

并發(fā)就是只有一個CPU資源伞剑,程序(或線程)之間要競爭得到執(zhí)行機會黎泣。第一個階段缤谎,在A執(zhí)行的過程中B坷澡,C不會執(zhí)? 行洋访,因為這段時間內(nèi)這個CPU資源被A競爭到了,同理呆抑,第二個階段只有B在執(zhí)行鹊碍,第三個階段只有C在執(zhí)行侈咕。其實耀销,并發(fā)過程? ? ?中熊尉,A掌腰, B齿梁,C并不是同時在進行的(微觀角度)。但又是同時進行的(宏觀角度)伦忠。

? ? ? ? ? ? ? ? ? ? ? ? ?微觀角度:微觀角度:所有的并發(fā)處理都有排隊等候缓苛,喚醒未桥,執(zhí)行等這樣的步驟冬耿,在微觀上他們都是序列被處理的萌壳,如果是同一時? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 刻到達的請求(或線程)也會根據(jù)優(yōu)先級的不同袱瓮,而先后進入隊列排隊等候執(zhí)行尺借。

? ? ? ? ? ? ? ? ? ? ? ? ? ?宏觀角度:多個幾乎同時到達的請求(或線程)在宏觀上看就像是同時在被處理

2燎斩、并行? :

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?指兩個或兩個以上事件(或線程)在同一時刻發(fā)生栅表,是真正意義上的不同事件或線程在同一時刻怪瓶,在不同CPU資源呢上? (多? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?????????核)洗贰,同時執(zhí)行哆姻。

? 簡易理解:

????????????????????????你在敲代碼矛缨,煙癮犯了箕昭,你一直到敲完了以后才去抽煙,這就說明你不支持并發(fā)也不支持并行泌霍。

? ? ? ? ? ? ? ? ? ? ????你敲代碼敲到一半朱转,煙癮犯了藤为,你停了下來抽空了根煙缅疟,抽完繼續(xù)敲代碼存淫,這說明你支持并發(fā)桅咆。

? ? ? ? ? ? ? ? ? ? ?????你敲代碼敲到一半轧邪,煙癮犯了忌愚,你一邊敲一邊抽煙硕糊,這說明你支持并行简十。

Fork子進程

程序:

? ??????????????編寫完的代碼螟蝙,在沒有運行的情況下民傻,稱之為程序场斑。

進程:

????????????????正在運行的程序稱為進程漏隐。? ? ? ? ?進程,除了包含代碼外取具,還需要運行環(huán)境等暇检,所以和程序是存在區(qū)別的占哟。

Fork:

????????????????python在os模塊中封裝了常用的系統(tǒng)調(diào)用榨乎,其中就有fork蜜暑。注意:fork只能在linux和mac中運行不能在windows中運行肛捍。

Python中的fork() 函數(shù)可以獲得系統(tǒng)中進程的PID ( Process ID )拙毫,返回0則為子進程缀蹄,否則就是父進程缺前,然后可以據(jù)此對運行中的進程進行操作衅码。


運行結(jié)果如下圖:


getpid垛玻、getppid:

os.getpid:獲得子進程編號

getppid:獲得父進程編號


運行結(jié)果如下圖所示(會無限循環(huán)下去因為用的是while True死循環(huán)):


多進程修改全局變量


其運行結(jié)果如下圖:


????????????????正常情況下后一個輸出結(jié)果應(yīng)該位1+1=2的巫糙,但是結(jié)果中顯示都是位1参淹,說明了進程間是無法共享數(shù)據(jù)的浙值。

????????????注意:多個進程間开呐,每個進程的所有數(shù)據(jù)(包括全局變量)都是各自擁有一份的,互不影響卵惦。

多個fork問題

同時進行多個fork


其結(jié)果如下圖:


主線程和子線程各執(zhí)行了一次,但是第三個和第四個都執(zhí)行了兩次

出現(xiàn)上圖結(jié)果的原因入下圖所示:


windows下實現(xiàn)多進程:multiprocessing



其運行結(jié)果如下圖:


????????????????從上面的運行結(jié)果中可以看出 主程序比子程序運行結(jié)束的要快,那么就需要用t1.join來進行約束(表示這個子進程運行完成才能進行主進程)

在上面的程序中是帶參數(shù)的啡捶,如果方法中不帶參數(shù) 則可以直接將參數(shù)去掉届慈。

類實現(xiàn)方式:

????????????????進程類的實現(xiàn)非常的簡單金顿,只要繼承了Process類就ok了鲤桥,重寫該類的run方法茶凳,run方法里面的代碼,就是我們需要的子進程代碼猪狈。

代碼如下圖:


運行結(jié)果如下


????????????????在進程類的實現(xiàn)中如果想要初始化一些前面我們提到過的參數(shù),如進程名稱等疆前,可以使用__init__借助父類來完成竹椒。(注意第一個屬性名稱具有特殊意義胸完,如果不用super().__init__將會無法進行修改)如下圖所示:


結(jié)果如下圖:


這時候的函數(shù)名字就是graves





阻塞/非阻塞、同步/異步:

????????????????在進行網(wǎng)絡(luò)變成時誓琼,長用到同步(Sync)/異步(Async)腹侣,阻塞(Block)/非阻塞(Unblock)四種調(diào)用方式:

同步:

????????????????所謂同步傲隶,就是在c端發(fā)出一個功能調(diào)用時跺株,在沒有得到結(jié)果之前乒省,該調(diào)用就不返回袖扛。也就是必須一件一件事做蛆封,等前一件做完了才能做下一件事惨篱。

異步:

????????????????當c端一個異步過程調(diào)用通過發(fā)出后砸讳,調(diào)用者不能立刻得到結(jié)果绣夺。實際處理這個調(diào)用的不見在完成后陶耍,通過狀態(tài)烈钞、通知和回調(diào)來通知調(diào)用者毯欣。

阻塞:

????????????????阻塞調(diào)用時值調(diào)用結(jié)果返回之前酗钞,當前線程會被掛起(線程進入非可執(zhí)行狀態(tài)砚作,在這個狀態(tài)下葫录,cpu不會給線程分配時間片米同,即線程暫停運行)面粮。函數(shù)只有在得到結(jié)果之后才會返回但金。

非阻塞:

????????????????非阻塞和阻塞的概念相對應(yīng)钱磅,指在不能立刻得到結(jié)果之前盖淡,該函數(shù)不會阻塞當前線程褪迟,而會立刻返回味赃。

進程池:

????????????????當我們需要的進程數(shù)量不多的時候心俗,我們可以使用multiprocessing的Process類來創(chuàng)建進程城榛。但是如果我們需要的進程特別多的時候狠持,手動創(chuàng)建工作量太大了喘垂,所以Python也為我們提供了Pool(池)的方式來創(chuàng)建大量進程王污。

其代碼入下圖所示:


運行結(jié)果如下圖所示:


注意:一般我們使用apply_async這個方法,表示非阻塞的運行阱驾,一旦使用了apply方法表示阻塞式執(zhí)行任務(wù),此時就是單任務(wù)執(zhí)行了(一般不會使用喧枷,特殊場景才會使用)

本地進程間的通信方式:

隊列(Queue)隧甚、管道(Pipe)戚扳、管理者(Manager)

隊列(queue)常用方法:

????????????Queue.qsize(): 返回queue中item的數(shù)量帽借,注意這個數(shù)量并不準確

????????????Queue.empty(): 如果隊列為空則返回True

????????????Queue.full():如果隊列充滿則返回True

????????????Queue.put(item[, block[, timeout]]): block表示是否阻塞砍艾,默認為True即阻塞凝垛,如果設(shè)定了timeout苔严,則阻塞timeout時長,如果仍然沒有空余的slot覆旭,則raise Queue.full exception型将。如果block=False七兜,那么就不阻塞腕铸,當queue full時,直接報Queue.full exception涛菠。寫入隊列對象

????????????Queue.get([block[, timeout]]) 獲得隊列對象

具體用法入下圖所示:


其運行結(jié)果為:

管道(Pipe):

????????????????????管道是一種兩個進程間進行單向通信的機制礁叔。因為管道傳遞數(shù)據(jù)的單向性言疗,管道又稱為半雙工管道晴圾。管道的這一特點決定了器使用的局限性。管道是Linux支持的最初Unix IPC形式之一噪奄,具有以下特點:

????? ????????????數(shù)據(jù)只能由一個進程流向另一個進程(其中一個讀管道死姚,一個寫管道);如果要進行雙工通信勤篮,需要建 立兩個管道都毒。

????? ????????????管道只能用于父子進程或者兄弟進程間通信碰缔。账劲,也就是說管道只能用于具有親緣關(guān)系的進程間通信。

用法與queue相似:

其運行結(jié)果為:

Manager:

????????????????Manager對象類似于服務(wù)器與客戶之間的通信金抡,做到了進程之間的數(shù)據(jù)共享瀑焦。Managers支持的數(shù)據(jù)類型有l(wèi)ist、dict梗肝、Namespace榛瓮、Lock、rlock巫击、Queue禀晓、Value、Arrayand so?on坝锰。

結(jié)果如下:

從圖中可以看出 manager做到了進程之間的數(shù)據(jù)共享

線程:

進程:

????????????????能夠完成多個任務(wù)粹懒,一般而言,一個進程就是一個獨立的軟件顷级,如我們在電腦上運行了多個QQ凫乖。進程(Process)是計算機中的程序關(guān)于某數(shù)據(jù)集合上的一次運行活動,是系統(tǒng)進行資源分配和調(diào)度的基本單位弓颈,是操作系統(tǒng)結(jié)構(gòu)的基礎(chǔ)帽芽。

線程:

? ? ? ? ? ? ? ?能夠完成多個任務(wù),一般而言恨豁,一個進程至少存在一個線程或者多個線程嚣镜,如打開網(wǎng)頁,啟動多個頁面選項卡橘蜜。線程菊匿,有時被稱為輕量級? ? ? ? ? ? ? ? ?進程(Lightweight Process付呕,LWP),是程序執(zhí)行流的最小單元跌捆。

注意:進程是程序的基本單位徽职,線程是程序的最小單位。類似于人們幣的基本單位是元佩厚,最小單位是分

兩者區(qū)別

????????????1姆钉、一個程序中至少有一個進程,一個進程中至少有一個線程抄瓦;

????????????2潮瓶、線程的劃分尺度小于進程(占有資源),使得多線程程序的并發(fā)性高钙姊;

????????????3毯辅、進程運行過程中擁有獨立的內(nèi)存空間,而線程之間共享內(nèi)存煞额,從而極大的提高了程序的運行效率

????????????4思恐、線程不能獨立運行,必須存在于進程中

? ? ? ? ? ?5膊毁、多線程和多進程的寫法很像胀莹,其次就是多線程的運行速度很快如果沒有join或者設(shè)置為守護線程,主線程會直接執(zhí)行后面的代碼婚温,之后掛起描焰,等待所有的子線程運行完成后結(jié)束,才能結(jié)束缭召。

線程優(yōu)缺點:線程開銷小栈顷,但是不利于資源的管理和保護

進程與之相反:進程開銷大逆日,但是利于資源的管理和保護嵌巷,安全比較有保障


多線程------threading:

????????????????????????????Python3中取消了thread模塊,只有threading模塊室抽,所以我們使用threading模塊來學習多線程編程搪哪。

其運行結(jié)果入下圖:

重寫run方法:


結(jié)果如下:


傳遞參數(shù)版:



1、 線程同樣會有名稱

2坪圾、 當run運行完成晓折,該線程就會自動結(jié)束

3、 我們無法控制線程兽泄,但是可以通過一些別的方式來影響線程調(diào)度

4漓概、 下圖是線程的幾種狀態(tài)


===================================================================================================

Python的GILGlobal?Interpreter Lock):

官方定義:

? ??????????????In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.)

????????????????定義說,GIL是多線程間的一把互斥鎖病梢,并且是一把全局鎖胃珍,它保證了Cpython在內(nèi)存管理上面是線程安全的梁肿。 這里要注意一點的是,官方定義開頭就給了限制范圍觅彰,是在CPython這個解釋器下吩蔑。我們知道,python存在各種各樣的解釋器填抬,也就是說烛芬,在某些解釋器下,其實并不存在GIL這個東西飒责,經(jīng)過查閱資料赘娄,像JPython中就不存在GIL。

? ? ? ? ? ? ? ?結(jié)論:在Cpython解釋器中宏蛉,同一個進程下開啟的多線程擅憔,同一時刻只能有一個線程執(zhí)行,無法利用多核優(yōu)勢檐晕。GIL并不是Python的特性暑诸,Python完全可以不依賴于GIL。

多線程-共享全局變量?:


結(jié)果


????????????????????在圖中可以看到兩個子線程是可以共享主線程的數(shù)據(jù)的辟灰。此時的數(shù)據(jù)較小个榕,但是如果數(shù)據(jù)很大的時候就會可能出現(xiàn)別的問題了:

????????????????????假設(shè)兩個線程t1和t2都要對No=0進?增1運算,t1和t2都各對No修改100萬次次芥喇,No的最終的結(jié)果應(yīng)該為2000000西采。但是由于是多線程訪問,有可能出現(xiàn)下?情況:在No=0時继控,t1取得No=0械馆。此時系統(tǒng)把t1調(diào)度為”sleeping”狀態(tài),把t2轉(zhuǎn)換為”running”狀態(tài)武通,t2也獲得No=0霹崎。然后t2對得到的值進?加1并賦給No,使得No=1冶忱。然后系統(tǒng)?把t2調(diào)度為”sleeping”尾菇,把t1轉(zhuǎn)為”running”。線程t1?把它之前得到的0加1后賦值給No囚枪。這樣派诬,明明t1和t2都完成了1次加1?作,但結(jié)果仍然是No=1链沼。如圖:


其結(jié)果為:


如果我們將代碼中的time.sleep(3)注釋去掉


????????????????問題產(chǎn)?的原因就是沒有控制多個線程對同?資源的訪問默赂,對數(shù)據(jù)造成破壞,使得線程運?的結(jié)果不可預(yù)期括勺。這種現(xiàn)象稱為“非線程安全”缆八。那么該怎么解決著這個問題呢谒臼?

????????????????系統(tǒng)調(diào)?t1,然后獲取到No的值為0耀里,此時上?把鎖蜈缤,即不允許其他現(xiàn)在操作No對No的值進?+1解鎖,此時No的值為1冯挎,其他的線程就可以使?No了逗扒,?且是No的值不是0?是1同理其他線程在對No進?修改時啡直,都要先上鎖颗品,處理完后再解鎖朽缎,在上鎖的整個過程中不允許其他線程訪問,就保證了數(shù)據(jù)的正確性翰守。通俗點就是:A去上廁所孵奶,進去后把廁所門鎖上了,B就不能進去蜡峰,要等到A出來將鎖打開了才能進去了袁。所以上述問題就得需要一把“鎖”來解決----互斥鎖

互斥鎖:

????????????????當多個線程?乎同時修改某?個共享數(shù)據(jù)的時候,需要進?同步控制線程同步能夠保證多個線程安全訪問競爭資源湿颅,最簡單的同步機制是引?互斥鎖载绿。

? ? ? ? ? ? ? ? 某個線程要更改共享數(shù)據(jù)時,先將其鎖定油航,此時資源的狀態(tài)為“鎖定”崭庸,其他線程不能更改;直到該線程釋放資源谊囚,將資源的狀態(tài)變成“?鎖定”怕享,其他的線程才能再次鎖定該資源×ぃ互斥鎖保證了每次只有?個線程進?寫?操作函筋,從?保證了多線程情況下數(shù)據(jù)的正確性。

threading模塊中定義了Lock類余境,常用方法有:

#創(chuàng)建鎖:mutex = threading.Lock()

#鎖定:mutex.acquire([blocking])

#釋放:mutex.release()

? ??????????????鎖定?法acquire可以有?個blocking參數(shù)驻呐。如果設(shè)定blocking為True灌诅,則當前線程會堵塞芳来,直到獲取到這個鎖為?(如果沒有指定,那么默認為True)猜拾,如果設(shè)定blocking為False即舌,則當前線程不會堵塞。


鎖的好處:

????????????????確保了某段關(guān)鍵代碼只能由?個線程從頭到尾完整地執(zhí)?

鎖的壞處:????????????????

? ? ? ? ? ? ? ? ? ?阻?了多線程并發(fā)執(zhí)?挎袜,包含鎖的某段代碼實際上只能以單線程模式執(zhí)?顽聂,效 率就??地下降了肥惭。由于可以存在多個鎖,不同的線程持有不同的鎖紊搪,并試圖獲取對?持有的鎖時蜜葱,可能會造成死鎖。

具體做法看圖說話:


結(jié)果如下:


?共享數(shù)據(jù):

結(jié)果如下:


非共享數(shù)據(jù)無需加鎖耀石,因為局部變量不是共享的牵囤,不能彼此影響。

在多線程開發(fā)中滞伟,全局變量是多個線程都共享的數(shù)據(jù)揭鳞,?局部變量等是各?線程的,是?共享的梆奈。所以不存在非線程安全問題野崇。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市亩钟,隨后出現(xiàn)的幾起案子乓梨,更是在濱河造成了極大的恐慌,老刑警劉巖清酥,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件督禽,死亡現(xiàn)場離奇詭異,居然都是意外死亡总处,警方通過查閱死者的電腦和手機狈惫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鹦马,“玉大人胧谈,你說我怎么就攤上這事≥┢担” “怎么了菱肖?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長旭从。 經(jīng)常有香客問我稳强,道長,這世上最難降的妖魔是什么和悦? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任退疫,我火速辦了婚禮,結(jié)果婚禮上鸽素,老公的妹妹穿的比我還像新娘褒繁。我一直安慰自己,他們只是感情好馍忽,可當我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布棒坏。 她就那樣靜靜地躺著燕差,像睡著了一般。 火紅的嫁衣襯著肌膚如雪坝冕。 梳的紋絲不亂的頭發(fā)上徒探,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天,我揣著相機與錄音喂窟,去河邊找鬼刹帕。 笑死,一個胖子當著我的面吹牛谎替,可吹牛的內(nèi)容都是我干的偷溺。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼钱贯,長吁一口氣:“原來是場噩夢啊……” “哼挫掏!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起秩命,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤尉共,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后弃锐,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體袄友,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年霹菊,在試婚紗的時候發(fā)現(xiàn)自己被綠了剧蚣。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡旋廷,死狀恐怖鸠按,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情饶碘,我是刑警寧澤目尖,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站扎运,受9級特大地震影響瑟曲,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜豪治,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一洞拨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鬼吵,春花似錦扣甲、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至涣脚,卻和暖如春示辈,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背遣蚀。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工矾麻, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人芭梯。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓险耀,卻偏偏與公主長得像,于是被迫代替她去往敵國和親玖喘。 傳聞我的和親對象是個殘疾皇子甩牺,可洞房花燭夜當晚...
    茶點故事閱讀 44,611評論 2 353

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

  • 在現(xiàn)實社會,我們經(jīng)常需要一種場景累奈,就是同時有多個事情需要執(zhí)行贬派,如在瀏覽網(wǎng)頁的同時需要聽音樂。比如說在跳舞的時候要唱...
    伊森H閱讀 814評論 2 2
  • 多任務(wù)的實現(xiàn)方式: 多進程模式 多線程模式 多進程 + 多線程 模式python即支持多進程澎媒,又支持多線程搞乏,如下進...
    viean閱讀 691評論 0 0
  • 又來到了一個老生常談的問題,應(yīng)用層軟件開發(fā)的程序員要不要了解和深入學習操作系統(tǒng)呢戒努? 今天就這個問題開始请敦,來談?wù)劜?..
    tangsl閱讀 4,124評論 0 23
  • 第一次看的電影居然是五四的微電影。储玫。冬三。大意了。缘缚。當時只是好奇勾笆,想去瞅一眼。桥滨。窝爪。 嘻嘻,給我切了水果約自習齐媒,像個賢惠...
    Snorlax143閱讀 162評論 1 1
  • 自有了工作餐后蒲每,就沒有動手,晚上也懶動手喻括,隨便吃邀杏,路過超市狂了一會,見到鮮鮮的雞內(nèi)珍,買了一合望蜡,一棵西蘭花...
    塵緣1227閱讀 226評論 2 0