線程、進程、協程/微線程

  • 併發的方式

併發處理是同一時間段內有幾個程序都在一個cpu中處於運行狀態,但任一時刻只有一個程序在cpu上運行。

多進程、多線程、IO多路複用(通過一種機制,可以監視多個描述符,一旦某個描述符就緒(一般是讀就緒或者寫就緒),能夠通知程序進行相應的讀寫操作。如select、poll、epoll)

  • 進程

        資源分配的基本單位,

        Linux系統函數fork()可在父進程中創建一個子進程,在父進程接到新請求時,複製出一個子進程來處理,即父進程監控請求,子進程處理,實現併發處理。注意:必須是Linux系統,windows不能用fork。

  • 進程的幾種狀態

(1)run(運行狀態):正在運行的進程或在等待隊列中等待的進程,等待的進程只要以得到cpu就可以運行

(2)Sleep(可中斷休眠狀態):相當於阻塞或在等待的狀態

(3)D(不可中斷休眠狀態):在磁盤上的進程

(4)T(停止狀態):這中狀態無法直觀的看見,因爲是進程停止後就釋放了資源,所以不會留在linux中

(5)Z(殭屍狀態):子進程先與父進程結束,但父進程沒有調用wait或waitpid來回收子進程的資源,所以子進程就成了殭屍進程,如果父進程結束後任然沒有回收子進程的資源,那麼1號進程將回收

  • 線程

      CPU調度和分配的基本單位,程序執行的最小單位。

       在同一時間片只能有一個線程針對一個cpu執行指令,而且其他的線程必須被掛起。然後內核調度程序不斷的喚醒/掛起線程來模擬多個任務的執行。

      一個進程可以由很多個線程組成,線程間共享進程的所有資源。線程有自己的堆棧、局部變量。

      線程的創建調用pthread_create

      線程中執行時一般都要進行同步和互斥,保證數據的一致性,因爲他們共享同一進程的所有資源。

      同步:防止競爭(因同時修改導致數據的不一致)

      互斥:使用互斥鎖防止多個線程同時讀寫某一塊內存區域。互斥鎖止允許一個線程進入臨界區。

      信號量:內存區域只允許固定個數的線程進入,就要使用信號量,防止線程之間產生衝突。信號量許多個線程同時進入臨界區。

 

  •  多線程的死鎖

  定義:是指由於兩個或者多個線程互相持有對方所需要的資源,相互等待資源,處於僵持狀態

  處理辦法:剝奪資源,或殺死其中一個線程

  • 多進程與多線程的區別與聯繫

(1)單位:進程是資源分配的最小單位,線程是程序執行/CPU調度的最小單位。

(2)地址空間:進程有獨立地址空間(用於建立數據表來維護代碼段、堆棧段和數據段);線程使用相同的地址空間(共享進程中的數據)

(3)開銷:CPU切換線程及創建線程的開銷比進程小(不需要開闢新的地址空間)進程間切換代價大,線程間切換代價小

(4)通信:同一進程間的線程間由於共享進程的數據,通信更方便,難點在於處理同步與互斥;而進程間的通信需要以IPC(進程間通信InterProcess Communication,如管道、消息隊列、信號量、共享內存)的方式進行通信

(5)健壯性:多進程程序更加健壯(多線程程序只要有一個線程死掉,整個進程也死掉了,而一個進程死掉並不會對另外一個進程造成影響,因爲進程有自己獨立的地址空間。)

(6)結束的影響:進程的結束會將它所擁有的所有線程銷燬,線程的銷燬不影響同個進程下的線程

(7)私有屬性:“線程有自己的私有屬性TCB,線程id,寄存器、硬件上下文,而進程也有自己的私有屬性進程控制塊PCB,這些私有屬性是不被共享的,用來標示一個進程或一個線程的標誌”

 

  • 協程、微線程

       協程,又稱微線程,纖程,coroutine 。

       協程是一個線程執行,兩個子過通過相互作完成某個任務。協程和子程序調用很像,但協程是在子程序內部中斷去執行別的子程序,適當時候返回接着執行,中斷有別於函數調用。

    舉個例子(協程的運作):

  

  • 協程與多線程的區別

(1)開銷。協程執行效率高,協程是單個線程執行,以子程序中斷的形式切換,沒有多線程切換的開銷。

(2)協程不需要多線程的鎖機制。不存在同時寫變量衝突。

  • 使用   yield+協程  實現生產者-消費者模型

       傳統的生產者-消費者模型是一個線程寫消息,一個線程取消息,使用鎖機制可能死鎖。如果改用協程,生產者生產消息後,直接通過yield跳轉到消費者開始執行,待消費者執行完畢後,切換回生產者繼續生產。

     yield一般配合send()方法使用:

send(value)將value值傳遞給yield表達式——下一次yield時返回值給send處——send——yield——。。。

程序:

def consumer():#消費者
    r = ''#r初始爲空字符,啓動生成器後變成'200 0K'
    while True:
        n = yield r#接收send的value作爲n,下一次運行時返回r給produce中的r
        if not n:#沒有生產時不能消費
            return
        print('[CONSUMER]Consuming %s...' % n)
        r = '200 OK'

def producer(c):#生產者
    c.send(None)#啓動生成器,啓動時必須value爲None
    n = 0
    while n < 5:
        n = n + 1
        print('[PRODUCER]Producing %s...' % n)
        r = c.send(n)#send將value傳遞給yield表達式的值,返回下一次運行yield時的值
        print('[PRODUCER]Consumer return: %s' % r)
    c.close()#生產完5個就結束

c = consumer()
producer(c)

運行結果:

[PRODUCER]Producing 1...
[CONSUMER]Consuming 1...
[PRODUCER]Consumer return: 200 OK
[PRODUCER]Producing 2...
[CONSUMER]Consuming 2...
[PRODUCER]Consumer return: 200 OK
[PRODUCER]Producing 3...
[CONSUMER]Consuming 3...
[PRODUCER]Consumer return: 200 OK
[PRODUCER]Producing 4...
[CONSUMER]Consuming 4...
[PRODUCER]Consumer return: 200 OK
[PRODUCER]Producing 5...
[CONSUMER]Consuming 5...
[PRODUCER]Consumer return: 200 OK

運行過程:

運行分析:

step1:produce(c),運行produce,運行到c.send(None)——運行c即consumer(),啓動生成器,value=None,不需要把value給什麼yield接收

step2:運行consumer()時運行遇到n=yield r,返回r=''作爲n,切換回producer中的原send處

step3:producer中首輪生產者生產n=1,遇到r=c.send(n),將value=n傳給yield所在表達式作爲n,此時n=1,消費者消費n=1

step4:在consumer()的while True循環,下一次運行yield所在表達式,返回此時的r=‘200 OK’給r

step5:在producer()中進行while的循環,n+1後變成2,進行:“send 切換到yield 再次yield 切換回send”的循環

step6:循環直到n=5,不再進入while,執行c.close()結束

  注意:

1.第一次啓動生成器c.send(None),value值爲None,啓動生成器時,調用c函數,不是到某個yield

2.send傳值是傳給了表達式,和yield後面是什麼沒有關係,再次遇到yield切換回原來send處。注意切換的位置以及傳回的是yield後面的值

3.傳回send是要把send的賦值表達式運行一次的,不是從send語句下面開始。

 

 

參考網址:

https://blog.csdn.net/zhou753099943/article/details/51771220

https://www.cnblogs.com/zhehan54/p/6130030.html

https://www.nowcoder.com/questionTerminal/234895a70e0b40e19db7f3fbaabc5fa3

https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/0013868328689835ecd883d910145dfa8227b539725e5ed000

https://blog.csdn.net/sunflowerduidui/article/details/51820067

https://www.cnblogs.com/zhang-can/p/7215506.html   這個鏈接講得比較深入,涉及到鎖/創建新線程/通信等等的程序,有需要可參考。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章