程序和執行緒

2021-08-22 17:51:44 字數 3991 閱讀 9452

## pthon 程序 vs 執行緒 ##

程序 vs 程式

編寫完畢的**,在沒有運⾏的時候,稱之為程式

正在運⾏著的**,就成為程序

程序,除了包含**以外,還有需要運⾏的環境等,所以和程式是有區別的

python的os模組封裝了常⻅的系統調⽤,其中就包括fork,(注意,fork函式,只在unix/linux/mac上運⾏,windows不可以 )可以在python程 序中輕鬆建立⼦程序

程式執⾏到os.fork()時,作業系統會建立⼀個新的程序(⼦程序),然後

python基礎語⾔

11進 程的建立-fork

複製⽗程序的所有資訊到⼦程序中 然後⽗程序和⼦程序都會從fork()函式中得到⼀個返回值,在⼦程序中這 個值⼀定是0,⽽⽗程序中是⼦程序的 id號

注意 : 在unix/linux作業系統中,提供了⼀個fork()系統函式,它⾮常特殊。

普通的函式調⽤,調⽤⼀次,返回⼀次,但是fork()調⽤⼀次,返回兩次,因 為作業系統⾃動把當前程序(稱為⽗程序)複製了⼀份(稱為⼦程序),然 後,分別在⽗程序和⼦程序內返回。

⼦程序永遠返回0,⽽⽗程序返回⼦程序的id。

這樣做的理由是,⼀個⽗程序可以fork出很多⼦程序,所以,⽗程序要記下 每個⼦程序的id,⽽⼦程序只需要調⽤getppid()就可以拿到⽗程序的id。

os.getpid() 用於獲取父程序id號

os.getppid() 用於獲取子程序id號

## 多程序修改全域性變數##

多程序中,每個程序中所有資料(包括全域性變數)都各有擁有1份,互不影響

## 關於多個程序的執行順序

父程序,子程序執行順序沒有規律,完全取決於作業系統的排程演算法

由於python是跨平台的,⾃然也應該提供⼀個跨平台的多程序⽀持。 multiprocessing模組就是跨平台版本的多程序模組。

multiprocessing模組提供了⼀個process類來代表⼀個程序物件

建立⼦程序時,只需要傳⼊⼀個執⾏函式和函式的引數,建立⼀個 process例項,⽤start()⽅法啟動,這樣建立程序⽐fork()還要簡單。 join()⽅法可以等待⼦程序結束後再繼續往下運⾏,通常⽤於程序間的同 步。

process([group [, target [, name [, args [, kwargs]]]]])

target:表示這個程序例項所調⽤物件;

args:表示調⽤物件的位置引數元組;

kwargs:表示調⽤物件的關鍵字引數字典;

name:為當前程序例項的別名;

group:⼤多數情況下⽤不到;

process類常⽤⽅法:

is_alive():判斷程序例項是否還在執⾏;

join([timeout]):是否等待程序例項執⾏結束,或等待多少秒;

start():啟動程序例項(建立⼦程序);

run():如果沒有給定target引數,對這個物件調⽤start()⽅法時,就將執 ⾏物件中的run()⽅法;

terminate():不管任務是否完成,⽴即終⽌;

process類常⽤屬性:

name:當前程序例項別名,預設為process-n,n為從1開始遞增的整 數;

pid:當前程序例項的pid值;

當需要建立的⼦程序數量不多時,可以直接利⽤multiprocessing中的process 動態成⽣多個程序,但如果是上百甚⾄上千個⽬標,⼿動的去建立程序的⼯ 作量巨⼤,此時就可以⽤到multiprocessing模組提供的pool⽅法。

初始化pool時,可以指定⼀個最⼤程序數,當有新的請求提交到pool中時, 如果池還沒有滿,那麼就會建立⼀個新的程序⽤來執⾏該請求;但如果池中 的程序數已經達到指定的最⼤值,那麼該請求就會等待,直到池中有程序結 束,才會建立新的程序來執⾏

process之間有時需要通訊,作業系統提供了很多機制來實現程序間的通訊。

1. queue的使⽤

可以使⽤multiprocessing模組的queue實現多程序之間的資料傳遞,queue 本身是⼀個訊息列隊程式

初始化queue()物件時(例如:q=queue()),若括號中沒有指定最⼤可接收 的訊息數量,或數量為負值,那麼就代表可接受的訊息數量沒有上限(直到 記憶體的盡頭);

queue.qsize():返回當前佇列包含的訊息數量;

queue.empty():如果隊列為空,返回true,反之false ;

queue.full():如果佇列滿了,返回true,反之false;

queue.get([block[, timeout]]):獲取佇列中的⼀條訊息,然後將其從列隊 中移除,block預設值為true;

1)如果block使⽤預設值,且沒有設定timeout(單位秒),訊息列隊如果為 空,此時程式將被阻塞(停在讀取狀態),直到從訊息列隊讀到訊息為⽌, 如果設定了timeout,則會等待timeout秒,若還沒讀取到任何訊息,則拋 出」queue.empty」異常;

如果block值為false,訊息列隊如果為空,則會⽴刻拋 出」queue.empty」異常;

queue.get_nowait():相當queue.get(false);

queue.put(item,[block[, timeout]]):將item訊息寫⼊佇列,block預設值 為true;

如果block使⽤預設值,且沒有設定timeout(單位秒),訊息列隊如果已 經沒有空間可寫⼊,此時程式將被阻塞(停在寫⼊狀態),直到從訊息列隊 騰出空間為⽌,如果設定了timeout,則會等待timeout秒,若還沒空間,則拋 出」queue.full」異常;

2)如果block值為false,訊息列隊如果沒有空間可寫⼊,則會⽴刻拋 出」queue.full」異常;

queue.put_nowait(item):相當queue.put(item, false);

python的thread模組是⽐較底層的模組,python的threading 模組是對thread做了⼀些包裝的,可以更加⽅便的被使⽤

建立好的執行緒,需要調⽤ start() ⽅法來啟動

python的threading.thread類有⼀個run⽅法,⽤於定義執行緒的功能函 數,可以在⾃⼰的執行緒類中覆蓋該⽅法。⽽建立⾃⼰的執行緒例項後,通 過thread類的start⽅法,可以啟動該執行緒,交給python虛擬機器進⾏調 度,當該執行緒獲得執⾏的機會時,就會調⽤run⽅法執⾏執行緒。

通過使⽤threading模組能完成多工的程式開 發,為了讓每個執行緒的封裝性更完美,所以使⽤threading模組時,往往會定 義⼀個新的⼦類class,只要繼承 threading.thread 就可以了,然後重 寫 run ⽅法

多執行緒程式的執⾏順序是不確定的。當執 ⾏到sleep語句時,執行緒將被阻塞(blocked),到sleep結束後,執行緒進⼊就 緒(runnable)狀態,等待排程。⽽執行緒排程將⾃⾏選擇⼀個執行緒執⾏

每個執行緒⼀定會有⼀個名字,儘管上⾯的例⼦中沒有指定執行緒物件的 name,但是python會⾃動為執行緒指定⼀個名字。

當執行緒的run()⽅法結束時該執行緒完成。

⽆法控制線程排程程式,但可以通過別的⽅式來影響執行緒排程的⽅式。

在⼀個程序內的所有執行緒共享全域性變數,能夠在不適⽤其他⽅式的前提下完成多執行緒之間的資料共享(這點要⽐多程序要好) 缺點就是,執行緒是對全域性變數隨意遂改可能造成多執行緒之間對全域性變數 的混亂(即執行緒⾮安全)

1.執行緒是程序的⼀個實體,是cpu排程和分派的基本單位,它是⽐程序更⼩的 能獨⽴運⾏的基本單位.執行緒⾃⼰基本上不擁有系統資源,只擁有⼀點在運 ⾏中必不可少的資源(如程式計數器,⼀組暫存器和棧),但是它可與同屬⼀ 個程序的其他的執行緒共享程序所擁有的全部資源.

2.⼀個程式⾄少有⼀個程序,⼀個程序⾄少有⼀個執行緒.

3.執行緒的劃分尺度⼩於程序(資源⽐程序少),使得多執行緒程式的併發性⾼。

4.程序在執⾏過程中擁有獨⽴的記憶體單元,⽽多個執行緒共享記憶體,從⽽極 ⼤地提⾼了程式的運⾏效率

5.線執行緒不能夠獨⽴執⾏,必須依存在程序中

6.執行緒執⾏開銷⼩,但不利於資源的管理和 保護;⽽程序正相反。

執行緒和程序

標準的定義是 程序是執行緒的容器,乙個程序可於乙個或者多個執行緒,它是系統分配資源的基本單位 同乙個程序下,執行緒共享位址空降 已經開啟的檔案 訊號處理函式 報警訊號和其他,執行緒自己只保留程式計數器和棧。但是很遺憾的,這個只是教科書上的定義,實際情況是每個作業系統實現的作業系統特性不同,實現的方法...

程序和執行緒

乙個程序就是當前正在執行的乙個程式,包括程式的暫存器 程式計數器和變數的當前值。不同的程序擁有不同的位址空間。而執行緒可以理解為是程序中的控制流。同乙個程序內也就是說在同乙個位址空間內可以有多個控制流。也就是可以有多個線 程,他們共享位址空間。我們通常將程序視為是資源的集合,程序中有程式的正文 資料...

執行緒和程序

對於求職者,在面試的時候大多都會被問到 你對多執行緒了解麼?給我講講執行緒和程序的區別吧。在unix中,乙個程序可以理解為執行緒 位址空間 檔案描述符 資料,道破現實,其實就相當於老闆和員工,老闆就是程序,員工就是執行緒。老闆需要僱傭若干員工 執行緒 還要有辦公樓 位址空間 還要有若干的辦公裝置 檔...