併發程式設計 程序與執行緒

2022-08-19 04:15:11 字數 3852 閱讀 2715

程序即正在執行的乙個過程。程序是對正在執行程式的乙個抽象。

程序的概念起源於作業系統,是作業系統最核心的概念,也是作業系統提供的最古老也是最重要的抽象概念之一。作業系統的其他所有內容都是圍繞程序的概念展開的。

ps:即使可以利用的cpu只有乙個(早期的計算機確實如此),也能保證支援(偽)併發的能力。將乙個單獨的cpu變成多個虛擬的cpu(多道技術:時間多路復用和空間多路復用+硬體上支援隔離),沒有程序的抽象,現代計算機將不復存在。

作業系統的作用:

1:隱藏醜陋複雜的硬體介面,提供良好的抽象介面

2:管理、排程程序,並且將多個程序對硬體的競爭變得有序

多程序詳細鏈結

1. 什麼是程序

程序就是乙個正在進行/執行的程式,換言之,程序指的是乙個程式的執行過程

程式vs程序:

程式:只是一堆**檔案

程序:程式執行的過程才是程序

序列:乙個任務完完整整地執行完畢,再執行下乙個任務,按次序依次進行

序列看起來就是乙個乙個執行的:對

乙個乙個的執行就是序列:錯誤

併發(切換+儲存狀態):多個任務看起來是同時執行,單核就可以實行併發

並行:多個任務是真正意義上的同時執行,只有多核才能實現並行

多道技術的產生背景:就是想要在單核下實現併發

ps:

現在的主機一般是多核,那麼每個核都會利用多道技術

有4個cpu,執行於cpu1的某個程式遇到io阻塞,會等到io結束再重新排程,會被排程到4個

cpu中的任意乙個,具體由作業系統排程演算法決定

如何實現:

1. 空間上的復用:將記憶體分為幾部分,每個部分放入乙個程式的資料,

這樣,同一時間記憶體中就有了多道程式的資料,為cpu在多個任務間切換做準備

2. 時間上的復用:多個程序共享cpu的時間

關鍵點就是cpu在多個任務之間進行切換

有兩種情況下會發生切換:

1. 乙個任務占用cpu時間過長(沒有遇到io操作):會降低效率

1. 乙個任務在執行的過程中遇到io操作: 可以提公升效率

2. 為何要用程序

要實現併發效果

同步

同步,就是在發出乙個功能呼叫時,在沒有得到結果之前,該呼叫就不會返回。按照這個定義,其實絕大多數函式都是同步呼叫。但是一般而言,我們在說同步、非同步的時候,特指那些需要其他部件協作或者需要一定時間完成的任務。

舉例: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,)

阻塞

#阻塞呼叫是指呼叫結果返回之前,當前執行緒會被掛起(如遇到io操作)。函式只有在得到結果之後才會將阻塞的執行緒啟用。有人也許會把阻塞呼叫和同步呼叫等同起來,實際上他是不同的。對於同步呼叫來說,很多時候當前執行緒還是啟用的,只是從邏輯上當前函式沒有返回而已。

#舉例:

#2. 阻塞呼叫:當socket工作在阻塞模式的時候,如果沒有資料的情況下呼叫recv函式,則當前執行緒就會被掛起,直到有資料為止。

非阻塞

#非阻塞和阻塞的概念相對應,指在不能立刻得到結果之前也會立刻返回,同時該函式不會阻塞當前執行緒。
1. 同步與非同步針對的是函式/任務的呼叫方式:同步就是當乙個程序發起乙個函式(任務)呼叫的時候,一直等到函式(任務)完成,而程序繼續處於啟用狀態。而非同步情況下是當乙個程序發起乙個函式(任務)呼叫的時候,不會等函式返回,而是繼續往下執行當,函式返回的時候通過狀態、通知、事件等方式通知程序任務完成。

2. 阻塞與非阻塞針對的是程序或執行緒:阻塞是當請求不能滿足的時候就將程序掛起,而非阻塞則不會阻塞當前程序

多執行緒詳細鏈結

執行緒顧名思義,就是一條流水線工作的過程,一條流水線必須屬於乙個車間,乙個車間的工作過程是乙個程序

關係:

程式------>程序(至少乙個主程序)------>執行緒(至少乙個主線程,依賴於程序)

程序只是用來把資源集中到一起(程序只是乙個資源單位,或者說資源集合),而執行緒才是cpu上的執行單位。

#

可以想象成北京地鐵與上海地鐵是不同的程序,而北京地鐵裡的13號線是乙個執行緒,北京地鐵所有的線路共享北京地鐵所有的資源,比如所有的乘客可以被所有線路拉。

生活中程序、執行緒

如果我們的軟體是乙個工廠,該工廠有多條流水線,流水線工作需要電源,電源只有乙個即cpu(單核cpu)

乙個車間就是乙個程序,乙個車間至少一條流水線(乙個程序至少乙個執行緒)

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

而建執行緒,就只是在乙個車間內造一條流水線,無需申請空間,所以建立開銷小

執行緒共享建立它的程序的位址空間                      程序有自己的位址空間。

執行緒可以直接訪問程序的資料段                         程序擁有父程序的資料段的自己的副本。

執行緒可以直接與程序的其他執行緒通訊                  程序必須使用程序間通訊來與兄弟程序通訊。

新執行緒很容易建立                                               新程序需要複製父程序。

執行緒可以對同一程序的執行緒進行相當大的控制    程序只能對子程序進行控制。

對主線程的更改(取消、優先順序更改等)可能會影響程序中其他執行緒的行為                對父程序的更改不會影響子程序。

多執行緒指的是,在乙個程序中開啟多個執行緒

1. 多執行緒共享乙個程序的位址空間

2. 執行緒比程序更輕量級,執行緒比程序更容易建立可撤銷,在許多作業系統中,建立乙個執行緒比建立乙個程序要快10-100倍,在有大量執行緒需要動態和快速修改時,這一特性很有用

3. 若多個執行緒都是cpu密集型的,那麼並不能獲得效能上的增強,但是如果存在大量的計算和大量的i/o處理,擁有多個執行緒允許這些活動彼此重疊執行,從而會加快程式執行的速度。

很形象的執行緒小故事

併發程式設計之程序與執行緒

2.2 並行與併發 2.3 應用 單核cpu下,多執行緒不能實際提高程式執行效率,只是為了能夠在不同的任務之間切換,不同執行緒輪流使用cpu,不至於乙個執行緒總占有cpu,別的執行緒沒法幹活。多核cpu可以並行跑多個執行緒,但能否提高程式執行效率還是要分情況的 1 有些任務,經過精心設計,將任務拆分...

併發程式設計 執行緒池與程序池

以時間換空間 程序池 乙個容器,這個容器限制住你開啟程序的數量,預設是os.cpu count 我的電腦是8核,所以能開啟8個,第一次肯定只能並行的處理8個任務,只要有任務完成,程序馬上就會接下乙個任務。實現 from concurrent.futures import processpoolexe...

併發程式設計(九) 多執行緒與多程序

本小節就乙個要求 掌握在乙個程序下開啟多個子程序與在乙個程序下開啟多個執行緒的區別 開始操作 from threading import thread def work print hello if name main for i in range 10 t thread target work t...