併發編程(進程與線程)

1、前言

進程即正在執行的一個過程。進程是對正在運行程序的一個抽象。html

進程的概念起源於操做系統,是操做系統最核心的概念,也是操做系統提供的最古老也是最重要的抽象概念之一。操做系統的其餘全部內容都是圍繞進程的概念展開的。   算法

PS:即便能夠利用的cpu只有一個(早期的計算機確實如此),也能保證支持(僞)併發的能力。將一個單獨的cpu變成多個虛擬的cpu(多道技術:時間多路複用和空間多路複用+硬件上支持隔離),沒有進程的抽象,現代計算機將不復存在。編程

 操做系統的做用:
    1:隱藏醜陋複雜的硬件接口,提供良好的抽象接口
    2:管理、調度進程,而且將多個進程對硬件的競爭變得有序

2、併發編程之多進程       

多進程詳細連接多線程

 1. 什麼是進程併發

    進程就是一個正在進行/運行的程序,換言之,進程指的是一個程序的運行過程

    程序vs進程:
        程序:只是一堆代碼文件
        進程:程序運行的過程纔是進程

    串行:一個任務完完整整地運行完畢,再執行下一個任務,按次序依次進行
        串行看起來就是一個一個運行的:對
        一個一個的運行就是串行:錯誤

    併發(切換+保存狀態):多個任務看起來是同時運行,單核就能夠實行併發
    並行:多個任務是真正意義上的同時運行,只有多核才能實現並行

    多道技術的產生背景:就是想要在單核下實現併發
   ps:
      如今的主機通常是多核,那麼每一個核都會利用多道技術
      有4個cpu,運行於cpu1的某個程序遇到io阻塞,會等到io結束再從新調度,會被調度到4個
      cpu中的任意一個,具體由操做系統調度算法決定
        如何實現:
              1. 空間上的複用:將內存分爲幾部分,每一個部分放入一個程序的數據,
         這樣,同一時間內存中就有了多道程序的數據,爲cpu在多個任務間切換作準備

       2. 時間上的複用:多個進程共享cpu的時間 關鍵點就是cpu在多個任務之間進行切換 有兩種狀況下會發生切換: 1. 一個任務佔用cpu時間過長(沒有遇到IO操做):會下降效率 1. 一個任務在運行的過程當中遇到IO操做: 能夠提高效率 2. 爲什麼要用進程 要實現併發效果

     

同步\異步 and 阻塞\非阻塞(重點)

同步app

同步,就是在發出一個功能調用時,在沒有獲得結果以前,該調用就不會返回。按照這個定義,其實絕大多數函數都是同步調用。可是通常而言,咱們在說同步、異步的時候,特指那些須要其餘部件協做或者須要必定時間完成的任務。 舉例:
  1. concurrent.futures.ProcessPoolExecutor().submit(func,).result()
2. concurrent.futures.ThreadPoolExecutor().submit(func,).result() 一提交便獲得結果

異步異步

異步的概念和同步相對。當一個異步功能調用發出後,調用者不能馬上獲得結果。當該異步功能完成後,經過狀態、通知或回調來通知調用者。若是異步功能用狀態來通知,那麼調用者就須要每隔必定時間檢查一次,效率就很低(有些初學多線程編程的人,總喜歡用一個循環去檢查某個變量的值,這實際上是一 種很嚴重的錯誤)。若是是使用通知的方式,效率則很高,由於異步功能幾乎不須要作額外的操做。至於回調函數,其實和通知沒太多區別。
舉例:
  1. concurrent.futures.ProcessPoolExecutor(3).submit(func,)
2. concurrent.futures.ThreadPoolExecutor(3).submit(func,)

 阻塞socket

#阻塞調用是指調用結果返回以前,當前線程會被掛起(如遇到io操做)。函數只有在獲得結果以後纔會將阻塞的線程激活。有人也許會把阻塞調用和同步調用等同起來,實際上他是不一樣的。對於同步調用來講,不少時候當前線程仍是激活的,只是從邏輯上當前函數沒有返回而已。
#舉例:
#1. 同步調用:apply一個累計1億次的任務,該調用會一直等待,直到任務返回結果爲止,但並未阻塞住(即使是被搶走cpu的執行權限,那也是處於就緒態);
#2. 阻塞調用:當socket工做在阻塞模式的時候,若是沒有數據的狀況下調用recv函數,則當前線程就會被掛起,直到有數據爲止。

 

非阻塞ide

#非阻塞和阻塞的概念相對應,指在不能馬上獲得結果以前也會馬上返回,同時該函數不會阻塞當前線程。

總結

1. 同步與異步針對的是函數/任務的調用方式:同步就是當一個進程發起一個函數(任務)調用的時候,一直等到函數(任務)完成,而進程繼續處於激活狀態。而異步狀況下是當一個進程發起一個函數(任務)調用的時候,不會等函數返回,而是繼續往下執行當,函數返回的時候經過狀態、通知、事件等方式通知進程任務完成。 2. 阻塞與非阻塞針對的是進程或線程:阻塞是當請求不能知足的時候就將進程掛起,而非阻塞則不會阻塞當前進程

 

3、併發編程之多線程

多線程詳細連接函數

一、什麼是線程

線程顧名思義,就是一條流水線工做的過程,一條流水線必須屬於一個車間,一個車間的工做過程是一個進程

關係:

程序------>進程(至少一個主進程)------>線程(至少一個主線程,依賴於進程)

進程只是用來把資源集中到一塊兒(進程只是一個資源單位,或者說資源集合),而線程纔是cpu上的執行單位。

 

#能夠想象成北京地鐵與上海地鐵是不一樣的進程,而北京地鐵裏的13號線是一個線程,北京地鐵全部的線路共享北京地鐵全部的資源,好比全部的乘客能夠被全部線路拉。
生活中進程、線程

 

二、建立線程的開銷小

若是咱們的軟件是一個工廠,該工廠有多條流水線,流水線工做須要電源,電源只有一個即cpu(單核cpu)

一個車間就是一個進程,一個車間至少一條流水線(一個進程至少一個線程)

建立一個進程,就是建立一個車間(申請空間,在該空間內建至少一條流水線)

而建線程,就只是在一個車間內造一條流水線,無需申請空間,因此建立開銷小

 

三、線程與進程的區別

程共享建立它的進程的地址空間                      程有本身的地址空間。

程能夠直接訪問進程的數據段                         程擁有父進程的數據段的本身的副本。

程能夠直接與進程的其餘線程通訊                  程必須使用進程間通訊來與兄弟進程通訊。

程很容易建立                                               新程須要複製父進程。

程能夠對同一進程的線程進行至關大的控制    程只能對子進程進行控制。

對主程的更改(取消、優先級更改等)可能會影響進程中其餘線程的行爲                對父程的更改不會影響子進程。

 

四、爲什麼多線程

多線程指的是,在一個進程中開啓多個線程

      1. 多線程共享一個進程的地址空間

      2. 線程比進程更輕量級,線程比進程更容易建立可撤銷,在許多操做系統中,建立一個線程比建立一個進程要快10-100倍,在有大量線程須要動態和快速修改時,這一特性頗有用

      3. 若多個線程都是cpu密集型的,那麼並不能得到性能上的加強,可是若是存在大量的計算和大量的I/O處理,擁有多個線程容許這些活動彼此重疊運行,從而會加快程序執行的速度。

  很形象的線程小故事

相關文章
相關標籤/搜索