Python - 進程、線程與協(xié)程

Python - 高級教程 - 進程挖函、線程與協(xié)程

進程與線程

在操作系統(tǒng)中状植,每一個獨立運行的程序,都占有 操作系統(tǒng) 分配的資源怨喘,這些程序中間互不干涉津畸,都只負責運行自己的程序代碼,這就是進程哲思。

image

但是當操作系統(tǒng)頻繁的創(chuàng)建銷毀進程時洼畅,大量的系統(tǒng)資源被浪費在創(chuàng)建和銷毀的過程中。而隨著多核心cpu 的出現(xiàn)棚赔,線程也逐漸代替了進程帝簇,成為了操作系統(tǒng) 可以獨立運行的基本單位。

image

當進程不是多線程程序時靠益,存在于進程當中的唯一線程丧肴,便是進程本身運行的代碼塊。

而當多線程出現(xiàn)在一個進程中時胧后,則多個線程之間共享此進程的資源芋浮,并接受操作系統(tǒng)的調(diào)度來運行每個線程。

狀態(tài)

image

協(xié)程

為了了解協(xié)程的概念壳快,我們先來了解一下并發(fā)和并行纸巷。

并行

并行比較好理解,即有多個程序在同時執(zhí)行眶痰,這里的程序指的是操作系統(tǒng)的線程瘤旨。

每個 cpu 核心,只能在同一個時刻運行一組指令竖伯,意味著同一時刻存哲,一個核心上只有一個線程在執(zhí)行因宇。

image

cpu 有四個核心時,他只可以并行執(zhí)行4個線程祟偷。

并發(fā)

想要了解并發(fā)察滑,就需要知道阻塞異步

同步阻塞

當程序中的一個 I/O 操作修肠,會占據(jù)比較長的時間贺辰,這時候,程序沒有被掛起氛赐,且一直在等待網(wǎng)絡數(shù)據(jù)傳輸魂爪,無法進行其他操作,這時候就是同步阻塞艰管。

image

同步的一個概念就是滓侍,網(wǎng)絡傳輸完成后也無法告知主程序操作完成,這就導致了主程序:

  • 要么只能進行等待 I/O 完成
  • 要么輪詢?nèi)ゲ榭词欠駛鬏斒欠褚呀?jīng)完成

當然牲芋,輪詢時候可以進行其他的操作撩笆,這時候,就是非阻塞的狀態(tài)缸浦,即 同步非阻塞夕冲。

同步非阻塞

非阻塞的概念即主程序可以進行其他的操作。

image

異步阻塞

有同步裂逐,就有異步歹鱼。

而異步阻塞與同步阻塞相同,主程序啥也不干卜高,就等著 I/O 操作完成弥姻。

image

異步非阻塞

異步非阻塞狀態(tài),便是并發(fā)的關鍵掺涛。

當主程序使用異步 I/O 操作時庭敦,并不會影響主程序后續(xù)的運行,而當異步 I/O 操作完成后薪缆,會主動通知主程序進行其他操作秧廉,這樣就減少了輪詢過程中的資源消耗,專注于其他工作拣帽。

image

并發(fā)

而并發(fā)就是 異步非阻塞 狀態(tài)下的一種形式疼电,當程序執(zhí)行操作 a 時,使 a 的 I/O 異步操作减拭,這時程序去執(zhí)行操作 b, 在外部看來澜沟,a 和 b 時同時被執(zhí)行的,然而他們只運行在在一個線程當中峡谊。

與線程、進程不同的是,協(xié)程并不是操作系統(tǒng)物理層面存在的一種程序既们。

協(xié)程是程序級別的濒析,由程序編寫者自己操控整個協(xié)程的生命周期。這樣就實現(xiàn)了類似操作系統(tǒng)操作多線程一樣的效果啥纸,但是省下了現(xiàn)成的切換中造成的資源消耗号杏。

而通過程序來操縱協(xié)程,就造成了cpu 一直在運行斯棒,并且是多個協(xié)程一直在運行的假象盾致,也就變成了并發(fā)。

實例

下面我們通過幾個實例來說明荣暮,在 python 中的進程庭惜、線程和協(xié)程的關系。

進程實例

python 中我們?nèi)绾尉帉懚噙M程的程序呢穗酥?

答案是使用模塊 multiprocessing 進行實現(xiàn)护赊。

import time
from multiprocessing import Process

class Test(Process):
    def __init__(self):
        super().__init__()
    
    def run(self):
        while True:
            print("process b is run")
            time.sleep(1)

通過繼承multiprocessingProcess,實現(xiàn)進程類砾跃,然后實現(xiàn) run 方法骏啰,即可在此方法中實現(xiàn)進程要運行的內(nèi)容。

from process_b import Test
import time

if __name__ == "__main__":
    t = Test()
    t.start()
    while True:
        print("process a run")
        time.sleep(1)


調(diào)用方法也非常簡單抽高,直接使用 Test 實例化對象判耕,然后調(diào)用對象的成員函數(shù)start() 即可。

python3 process_a.py
process a run
process b is run
process b is run
process a run
process a run
process b is run
process b is run
process a run

線程實例

Cpython 中由于存在 GIL翘骂,所以多線程在實際應用中也會變?yōu)閱魏?code>cpu 上的線程壁熄,排隊運行。

import threading
import time

class ThreadTest (threading.Thread):
    def __init__(self, name):
        super().__init__()
        self.name = name

    def run(self):
        while True:
            print(f"i am in thread {self.name}")
            time.sleep(1)


if __name__ == "__main__":
    threads = []
    for i in range(4):
        t = ThreadTest(i)
        threads.append(t)
    
    for t in threads:
        t.start()
    
    for t in threads:
        t.join()

通過繼承 threading.Thread 來實現(xiàn)線程類雏胃,然后通過實例化请毛,生成對象,調(diào)用對象的 start() 即可啟動線程瞭亮。

運行結果

python3 thread_a.py
i am in thread 0
i am in thread 1
i am in thread 2
i am in thread 3
i am in thread 1
i am in thread 3
i am in thread 0
i am in thread 2
i am in thread 1
i am in thread 3
i am in thread 0
i am in thread 2
i am in thread 1

協(xié)程

python3asyncio 加入到了標準庫方仿。

import asyncio
import time


async def test(num):
    await asyncio.sleep(num)
    print(num)


async def run():
    tasks = [asyncio.create_task(test(num)) for num in range(4)]
    [await t for t in tasks]


def run_main():
    asyncio.run(run())


if __name__ == "__main__":
    run_main()

運行結果

import asyncio
import time


async def test(num):
    await asyncio.sleep(num)
    print(num)


async def run():
    tasks = [asyncio.create_task(test(num)) for num in range(4)]
    [await t for t in tasks]


def run_main():
    asyncio.run(run())


if __name__ == "__main__":
    run_main()

總結

以上就是本節(jié)的所有內(nèi)容,主要簡單地講解了關于 進程统翩、線程和協(xié)程 的概念和例子仙蚜。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市厂汗,隨后出現(xiàn)的幾起案子委粉,更是在濱河造成了極大的恐慌,老刑警劉巖娶桦,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件贾节,死亡現(xiàn)場離奇詭異汁汗,居然都是意外死亡,警方通過查閱死者的電腦和手機栗涂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進店門知牌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人斤程,你說我怎么就攤上這事角寸。” “怎么了忿墅?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵扁藕,是天一觀的道長。 經(jīng)常有香客問我疚脐,道長亿柑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任亮曹,我火速辦了婚禮橄杨,結果婚禮上,老公的妹妹穿的比我還像新娘照卦。我一直安慰自己式矫,他們只是感情好,可當我...
    茶點故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布役耕。 她就那樣靜靜地躺著采转,像睡著了一般。 火紅的嫁衣襯著肌膚如雪瞬痘。 梳的紋絲不亂的頭發(fā)上故慈,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天,我揣著相機與錄音框全,去河邊找鬼察绷。 笑死,一個胖子當著我的面吹牛津辩,可吹牛的內(nèi)容都是我干的拆撼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼喘沿,長吁一口氣:“原來是場噩夢啊……” “哼闸度!你這毒婦竟也來了?” 一聲冷哼從身側響起蚜印,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤莺禁,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后窄赋,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體哟冬,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡楼熄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了浩峡。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片孝赫。...
    茶點故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖红符,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情伐债,我是刑警寧澤预侯,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站峰锁,受9級特大地震影響萎馅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜虹蒋,卻給世界環(huán)境...
    茶點故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一糜芳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧魄衅,春花似錦峭竣、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至哲银,卻和暖如春扛吞,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背荆责。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工滥比, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人做院。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓盲泛,卻偏偏與公主長得像,于是被迫代替她去往敵國和親山憨。 傳聞我的和親對象是個殘疾皇子查乒,可洞房花燭夜當晚...
    茶點故事閱讀 45,507評論 2 359

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