最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊

【并發(fā)操作】協(xié)程,線程,進(jìn)程是什么,在Python中怎么應(yīng)用?

2022-08-12 16:59 作者:騰訊藍(lán)鯨智云  | 我要投稿

前言

生活中的多任務(wù)時(shí)時(shí)刻刻存在,例如小張一邊碼字一邊看屏幕,又例如小蔡可以一邊跳舞一邊打籃球,這就是生活中的多任務(wù)。那么計(jì)算機(jī)中的多任務(wù)是什么呢、怎么使用呢?就讓我們一起探討計(jì)算機(jī)中,多任務(wù)-線程、多任務(wù)-進(jìn)程、多任務(wù)-協(xié)程的理解以及在Python中的應(yīng)用。

多任務(wù)

多任務(wù)處理是指用戶可以在同一時(shí)間內(nèi)進(jìn)行多種操作,每個(gè)操作被稱作一個(gè)任務(wù)。在計(jì)算機(jī)中,同時(shí)打開迅雷以及QQ是多任務(wù)同時(shí)進(jìn)行,在迅雷中看電影的時(shí)候,進(jìn)行邊下邊播也是多任務(wù),在同一時(shí)間同一單位進(jìn)行的不同操作,都可以理解為多任務(wù)。

現(xiàn)在多核CPU已經(jīng)非常普及了,但事實(shí)上,過去即便是單核CPU也可以執(zhí)行多任務(wù)。由于CPU執(zhí)行代碼都是順序執(zhí)行的,那單核CPU是怎么執(zhí)行多任務(wù)的呢?

答案就是操作系統(tǒng)輪流讓各個(gè)任務(wù)交替執(zhí)行,任務(wù)1執(zhí)行0.01秒,切換到任務(wù)2,任務(wù)2執(zhí)行0.01秒,再切換到任務(wù)3,……這樣反復(fù)執(zhí)行下去。表面上看,每個(gè)任務(wù)都是交替執(zhí)行的,但是,由于CPU的執(zhí)行速度實(shí)在是太快了,我們感覺就像所有任務(wù)都在同時(shí)執(zhí)行。

真正實(shí)現(xiàn)并行執(zhí)行多任務(wù)只能在多核CPU上實(shí)現(xiàn),但往往任務(wù)數(shù)量遠(yuǎn)遠(yuǎn)多于CPU的核心數(shù)量,所以操作系統(tǒng)也會(huì)自動(dòng)把很多任務(wù)輪流調(diào)度到每個(gè)核心上執(zhí)行。在這里我們引入并發(fā)與并行以及隊(duì)列的概念:

并發(fā):

cpu通過在任務(wù)間快速切換達(dá)到多任務(wù)一起執(zhí)行,但實(shí)際上并不是同時(shí)執(zhí)行,舉例:

A和B去跑步,跑道很擠只能容納一個(gè)人,兩人約定好每人跑一秒,大家都跑一秒就退出跑道。這時(shí),在同一時(shí)間內(nèi),總有一個(gè)人在跑道內(nèi)、一個(gè)人在跑道外(下圖中兩隊(duì)人排同一個(gè)咖啡機(jī)即為并發(fā))

并行:

每個(gè)任務(wù)都有不同cpu去執(zhí)行,達(dá)到多任務(wù)一起執(zhí)行,實(shí)際是真正的同時(shí)執(zhí)行,舉例還是A和B兩人去跑步。這次跑道升級(jí)了,有兩條跑道,A和B實(shí)現(xiàn)了并肩奔跑,你我互不影響(圖中兩隊(duì)人排兩臺(tái)咖啡機(jī)即為并行)

隊(duì)列:

就是一個(gè)有序的排列,在多任務(wù)中需要把待執(zhí)行的任務(wù)排好隊(duì),有序執(zhí)行。在A和B跑步的例子中,假設(shè)有20個(gè)A和20個(gè)B需要跑步,在排隊(duì)等待跑步的時(shí)候,形成的排列就稱為隊(duì)列(圖中兩個(gè)隊(duì)伍即為隊(duì)列)



思考:迅雷播放電影的同時(shí)用QQ聊天,和在迅雷中看電影邊下邊播多任務(wù)有什么不同?

01 線程

  • 一個(gè)程序運(yùn)行起來至少有一個(gè)進(jìn)程,一個(gè)進(jìn)程至少有一個(gè)線程;

  • 處理器cpu分配給線程,即cpu真正運(yùn)行的是線程中的代碼;

  • 分配cpu給線程時(shí),是通過時(shí)間片輪訓(xùn)方式進(jìn)行的;

  • 進(jìn)程是操作系統(tǒng)分配程序執(zhí)行資源的單位,而線程是進(jìn)程的一個(gè)實(shí)體;

  • 是CPU調(diào)度和分配的單位。

在上述思考中,迅雷和QQ屬于不同的進(jìn)程,迅雷下載電影和播放電影屬于不同的線程,即一開始分配了兩份資源給迅雷和QQ,迅雷和QQ各為一個(gè)進(jìn)程。

當(dāng)你打開迅雷邊下邊播功能的時(shí)候,在迅雷這個(gè)進(jìn)程中又新開了兩個(gè)線程,不斷地在下載和播放間進(jìn)行切換,達(dá)到多任務(wù)的效果. ?線程與進(jìn)程是屬于關(guān)系。

線程由進(jìn)程創(chuàng)建,進(jìn)程結(jié)束線程也結(jié)束了,但線程結(jié)束進(jìn)程不一定結(jié)束,cpu最終分配給的是線程,而不是進(jìn)程。

線程執(zhí)行代碼片段原理:線程獲得cpu執(zhí)行內(nèi)存,執(zhí)行當(dāng)前代碼,在執(zhí)行另一個(gè)代碼塊之前打上時(shí)間戳,存儲(chǔ)上下文然后去執(zhí)行另一代碼塊。當(dāng)再次回到該代碼塊時(shí)加載時(shí)間戳,上下文,驗(yàn)證執(zhí)行的合理性,如此反復(fù)執(zhí)行下去,在不同的需要執(zhí)行的代碼塊間切換。



子線程何時(shí)開啟,何時(shí)運(yùn)行?

當(dāng)調(diào)用thread.start()時(shí) 開啟線程,再運(yùn)行線程的代碼。

子線程何時(shí)結(jié)束?

子線程把target指向的函數(shù)中的語句執(zhí)行完畢后,或者線程中的run函數(shù)代碼執(zhí)行完畢后,立即結(jié)束當(dāng)前子線程。

查看當(dāng)前線程數(shù)量

通過threading.enumerate()可枚舉當(dāng)前運(yùn)行的所有線程。

主線程何時(shí)結(jié)束?

所有子線程執(zhí)行完畢后,主線程才結(jié)束。

02 進(jìn)程

進(jìn)程:

一個(gè)程序運(yùn)行起來后,“代碼+用到的資源”稱之為進(jìn)程,它是操作系統(tǒng)分配資源的基本單位。

進(jìn)程狀態(tài):

工作中,任務(wù)數(shù)往往大于cpu的核數(shù),即一定有一些任務(wù)正在執(zhí)行,另外一些任務(wù)在等待cpu進(jìn)行執(zhí)行,因此導(dǎo)致了有了不同的狀態(tài)。



就緒態(tài):

運(yùn)行的條件都已經(jīng)滿足,正在等在cpu執(zhí)行。

執(zhí)行態(tài):

cpu正在執(zhí)行其功能。

等待態(tài):

等待某些條件滿足,例如一個(gè)程序sleep了,此時(shí)就處于等待態(tài),好比說:紅綠燈、等待消息回復(fù)、等待同步鎖都是處于等待態(tài)。

03 協(xié)程

協(xié)程是Python中另外一種實(shí)現(xiàn)多任務(wù)的方式,只不過比線程更小占用、執(zhí)行單元,由于協(xié)程是本世紀(jì)出現(xiàn)的新概念,所以對于協(xié)程來說沒有統(tǒng)一的概念,這里介紹我自己的理解,協(xié)程相當(dāng)于更便捷更輕量的線程。

協(xié)程與線程差異在于,實(shí)現(xiàn)多任務(wù)時(shí), 線程切換從系統(tǒng)層面遠(yuǎn)不止保存和恢復(fù) CPU上下文這么簡單。操作系統(tǒng)為了程序運(yùn)行的高效性,每個(gè)線程都有自己緩存Cache等數(shù)據(jù),操作系統(tǒng)還會(huì)幫你做這些數(shù)據(jù)的恢復(fù)操作。所以線程的切換非常耗性能。但是協(xié)程的切換只是單純操作CPU的上下文,所以一秒鐘切換個(gè)上百萬次系統(tǒng)都扛得住。

04 隊(duì)列與他們的關(guān)系

三者在工作時(shí)都需要取得cpu,為了避免彼此之間爭奪cpu,所以需要對他們進(jìn)行排隊(duì)處理,排好的隊(duì)伍就叫隊(duì)列,例如線程池、進(jìn)程池。



05 三者間的關(guān)系

進(jìn)程>線程>協(xié)程

線程由進(jìn)程創(chuàng)建,屬于進(jìn)程,協(xié)程是進(jìn)程更小程度的劃分,更輕便靈活,如下圖:


在Python中實(shí)現(xiàn)多任務(wù)

01 Python實(shí)現(xiàn)多線程



  • 自定義類,繼承threading.Thread;

  • 創(chuàng)建對象;

  • 調(diào)用對象的run()方法。

02 Python實(shí)現(xiàn)多進(jìn)程


  • 實(shí)例化一個(gè)對象 target= 指定到對應(yīng)的函數(shù);

  • 調(diào)用對象的run()方法。

03 Python實(shí)現(xiàn)多協(xié)程


  • 函數(shù)中調(diào)用yield;

  • 調(diào)用yield后函數(shù)會(huì)在執(zhí)行到調(diào)用send() 方法結(jié)果返回時(shí)才繼續(xù)進(jìn)行下一步;

  • 執(zhí)行函數(shù),函數(shù)會(huì)交替執(zhí)行。

多任務(wù)的痛點(diǎn)及解決方法

01 痛點(diǎn)1

如果多個(gè)線程同時(shí)對一個(gè)全局變量操作,會(huì)出現(xiàn)資源競爭問題,從而數(shù)據(jù)結(jié)果會(huì)不正確。


運(yùn)行上述代碼后會(huì)發(fā)現(xiàn)兩個(gè)線程對同一個(gè)數(shù)據(jù)操作完后得到的數(shù)據(jù)不一樣,這就是遇到了線程安全問題。

解決方法: 同步就是協(xié)同步調(diào),按預(yù)定的先后次序運(yùn)行。如:你說完,我再說;你做完,我再做;你執(zhí)行完,我再執(zhí)行。

在多線程編程中,一些敏感數(shù)據(jù)不允許被多個(gè)線程同時(shí)訪問,因?yàn)闀?huì)出現(xiàn)線程安全問題。通過線程同步機(jī)制,能保證共享數(shù)據(jù)在任何時(shí)刻,最多有一個(gè)線程訪問,以保證數(shù)據(jù)的正確性。線程同步提示的幾點(diǎn):

  1. 線程同步就是線程排隊(duì);

  2. 共享資源的讀寫才需要同步;

  3. 變量才需要同步,常量不需要同步;

  4. 給數(shù)據(jù)加鎖,即我操作完你再操作,你操作完我再操作。

threading模塊中定義了Lock類,可以方便的處理鎖定:



02 痛點(diǎn)2

GIL全局解釋器鎖:顧名思義,這是解釋器內(nèi)部的一把鎖,確切一點(diǎn)說是CPython解釋器內(nèi)部的一把鎖,所以要注意區(qū)分我們在Python代碼中使用的Lock不是一個(gè)層面的概念。言外之意,就是全局解釋器就是為了鎖定整個(gè)解釋器內(nèi)部的全局資源,每個(gè)線程想要運(yùn)行首先獲取GIL,而GIL本身又是一把互斥鎖,造成所有線程只能一個(gè)一個(gè)one-by-one-并發(fā)-交替的執(zhí)行。

也就是說Python中多線程并不能很好的實(shí)現(xiàn)并發(fā)操作,但Python恰好又是實(shí)現(xiàn)多協(xié)程的一種方法,所以對于Python來說,實(shí)現(xiàn)多任務(wù)最好的方式即為多進(jìn)程+多協(xié)程。

擴(kuò)展 celery原理

celery是基于Python實(shí)現(xiàn)的一個(gè)異步任務(wù)的調(diào)度工具,同時(shí)還是一個(gè)任務(wù)隊(duì)列,主要用于處理耗時(shí)的任務(wù)。

大家在使用celery的時(shí)候,都需要去配置一個(gè)隊(duì)列才能繼續(xù)使用,因?yàn)閷τ赾elery來說,也是一個(gè)生產(chǎn)者消費(fèi)者的模式,我們一般使用的隊(duì)列是Redis或者RabbitMQ,因?yàn)榇鎯?chǔ)格式為鍵值對形式,序號(hào)對應(yīng)任務(wù),利于cpu執(zhí)行。celery即為消息中間件,任務(wù)執(zhí)行單元,任務(wù)執(zhí)行結(jié)果儲(chǔ)存的形式進(jìn)行異步操作,如圖:


總結(jié)

請看如下例子: 有一個(gè)老板想要開個(gè)工廠進(jìn)行生產(chǎn)剪子,他需要花一些財(cái)力物力制作一條生產(chǎn)線,這個(gè)生產(chǎn)線上有很多的器件以及材料這些所有的,為了能夠生產(chǎn)剪子而準(zhǔn)備的資源稱之為:進(jìn)程

只有生產(chǎn)線是不能夠進(jìn)行生產(chǎn)的,所以老板的找個(gè)工人來進(jìn)行生產(chǎn),這個(gè)工人能夠利用這些材料最終一步步的將剪子做出來,這個(gè)來做事情的工人稱之為:線程

這個(gè)老板為了提高生產(chǎn)率,想到3種辦法:

  • 在這條生產(chǎn)線上多招些工人,一起來做剪子,這樣效率是成倍増長,即單進(jìn)程 多線程方式

  • 老板發(fā)現(xiàn)這條生產(chǎn)線上的工人不是越多越好,因?yàn)橐粭l生產(chǎn)線的資源以及材料畢竟有限,所以老板又花了些財(cái)力物力購置了另外一條生產(chǎn)線,然后再招些工人這樣效率又再一步提高了,即多進(jìn)程 多線程方式。

  • 老板發(fā)現(xiàn),現(xiàn)在已經(jīng)有了很多條生產(chǎn)線,并且每條生產(chǎn)線上已經(jīng)有很多工人了(即程序是多進(jìn)程的,每個(gè)進(jìn)程中又有多個(gè)線程),為了再次提高效率,老板想了個(gè)損招,規(guī)定:如果某個(gè)員工在上班時(shí)臨時(shí)沒事或者再等待某些條件(比如等待另一個(gè)工人生產(chǎn)完某道工序 之后他才能再次工作) ,那么這個(gè)員工就利用這個(gè)時(shí)間去做其它的事情,那么也就是說:如果一個(gè)線程等待某些條件,可以充分利用這個(gè)時(shí)間去做其它事情,其實(shí)這就是:協(xié)程方式。

簡單來說:

1. 進(jìn)程是操作系統(tǒng)資源分配的單位;

2. 線程是CPU調(diào)度的單位;

3. 進(jìn)程切換需要的資源最大,效率很低;

4. 線程切換需要的資源一般,效率一般(當(dāng)然在不考慮GIL的情況下);

5. 協(xié)程切換任務(wù)資源很小,效率高;

6. 多進(jìn)程、多線程根據(jù)cpu核數(shù)不一樣可能是并行的,但是協(xié)程是在一個(gè)線程中所以是并發(fā)。

藍(lán)鯨智云

本文由騰訊藍(lán)鯨智云編輯發(fā)布,騰訊藍(lán)鯨智云(簡稱藍(lán)鯨)軟件體系是一套基于PaaS的技術(shù)解決方案,致力于打造行業(yè)領(lǐng)先的一站式自動(dòng)化運(yùn)維平臺(tái)。目前已經(jīng)推出社區(qū)版、企業(yè)版,歡迎體驗(yàn)。

  • 官網(wǎng):https://bk.tencent.com/

  • 下載鏈接:https://bk.tencent.com/download/

  • 社區(qū):https://bk.tencent.com/s-mart/community/question


【并發(fā)操作】協(xié)程,線程,進(jìn)程是什么,在Python中怎么應(yīng)用?的評(píng)論 (共 條)

分享到微博請遵守國家法律
平顶山市| 巩留县| 东乌| 葫芦岛市| 连州市| 元江| 论坛| 徐闻县| 精河县| 武陟县| 新乡市| 贵定县| 曲阳县| 芦溪县| 乳山市| 广宁县| 永城市| 高平市| 拉萨市| 沂水县| 梅州市| 阿鲁科尔沁旗| 屯昌县| 和田县| 丰镇市| 晋宁县| 韩城市| 嘉定区| 平谷区| 前郭尔| 双牌县| 舒城县| 梓潼县| 长白| 阳新县| 平远县| 建始县| 巴林右旗| 盐边县| 乳山市| 湖南省|