day5-程序、線程、協程
1.程序
程序是計算機中的程式關于某資料集合上的一次運作活動,是系統進行資源配置設定和排程的基本機關,是作業系統結構的基礎
2.程序的優點:
動态性:程序是程式的一次執行過程,是臨時的,有生命期的,是動态産生,動态消亡的;
并發性:任何程序都可以同其他進行一起并發執行;
獨立性:程序是系統進行資源配置設定和排程的一個獨立機關;
結構性:程序由程式,資料和程序控制塊三部分組成
3.程序缺點
a.程序的建立和銷毀過程需要消耗較多的計算機資源
b.資源消耗過多
4.程序代碼
import time
import multiprocessing
def dance():
while True:
print("跳舞")
time.sleep(1)
def song():
while True:
print("唱歌")
time.sleep(1)
def main():
"""一邊唱歌一邊跳舞"""
p1 = multiprocessing.Process(target=dance)
p2 = multiprocessing.Process(target=song)
p1.start()
p2.start()
time.sleep(3)
# 程序結束
p1.terminate()
p2.terminate()
if __name__ == '__main__':
main()
5.線程
線程是作業系統能夠進行運算排程的最小機關。它被包含在程序之中,是程序中的實際運作機關。一條線程指的是程序中一個單一順序的控制流,一個程序中可以并發多個線程,每條線程并行執行不同的任務,同一程序下的線程不僅共享程序資源和記憶體,每個線程還可有一個屬于它自己的記憶體空間——線程棧
6.線程的優點
a.線程間切換快
b.共享資料
c.多核cpu使用率
7.線程的缺點
a.每個線程與主程式共用位址空間,受限于2GB位址空間;
b.線程之間的同步和加鎖控制比較麻煩;
c.線程沒有獨立的空間,一個線程死掉整個程序都會挂掉
8.線程代碼
import threading
import time
from time import sleep
def sing():
for i in range(3):
print("正在唱歌...%d" % i)
sleep(1)
def dance():
for i in range(3):
print("正在跳舞...%d" % i)
sleep(1)
# 子線程全部執行完 主線程才會結束 程式也就結束了
if __name__ == '__main__':
t1 = threading.Thread(target=sing)
t2 = threading.Thread(target=dance)
# 開啟兩個子線程
t1.start()
t2.start()
# print(t1.name)
# print(t2.name)
while True:
# 擷取目前有幾個線程
length = len(threading.enumerate())
print(length)
if length == 1:
break
time.sleep(0.5)
9.協程
協程是python個中另外一種實作多任務的方式,隻不過比線程更小占用更小執行單元(了解為需要的資源)。 為啥說它是一個執行單元,因為它自帶CPU上下文。這樣隻要在合适的時機, 我們可以把一個協程 切換到另一個協程。 隻要這個過程中儲存或恢複 CPU上下文那麼程式還是可以運作的。
通俗的了解:在一個線程中的某個函數,可以在任何地方儲存目前函數的一些臨時變量等資訊,然後切換到另外一個函數中執行,注意不是通過調用函數的方式做到的,并且切換的次數以及什麼時候再切換到原來的函數都由開發者自己确定
10協程的優點
a.協程是使用者自己控制切換的時機,不再需要陷入系統的核心态
b.協程的執行效率非常高。因為子程式切換不是線程切換,而是由程式自身控制
c.不需要多線程的鎖機制。由于隻有一個線程,也不存在同時寫變量的沖突,在協程中控制共享資源不需要加鎖,隻需要判斷資料的狀态,是以執行效率遠高于線程 ,對于多核CPU可以使用多程序+協程來盡可能高效率地利用CPU
11.協程的缺點
a.無法利用多核資源:協程的本質是個單線程,它不能同時将 單個CPU 的多個核用上,協程需要和程序配合才能運作在多CPU上.當然我們日常所編寫的絕大部分應用都沒有這個必要,除非是cpu密集型應用。
b.進行阻塞操作(如IO時)會阻塞掉整個程式
12.協程代碼
import time
def work1():
while True:
print("----work1---")
yield
time.sleep(0.5)
def work2():
while True:
print("----work2---")
yield
time.sleep(0.5)
def main():
# 擷取w1 w2 兩個生成器對象
w1 = work1()
w2 = work2()
while True:
next(w1)
next(w2)
if __name__ == "__main__":
main()
13.程序和線程的差別
a. 一個程式中至少有一個程序,一個程序中至少有一個線程;
b. 線程的劃分尺度小于程序(占有資源),使得多線程程式的并發性高;
c. 程序運作過程中擁有獨立的記憶體空間,而線程之間共享記憶體,進而極大的提高了程式的運作效率
d.線程不能獨立運作,必須存在于程序中
e.線程是程式執行的最小機關,而程序是作業系統配置設定資源的最小機關
f.排程和切換:線程上下文切換比程序上下文切換要快得多
14.線程和協程的差別
a.一個線程可以多個協程,一個程序也可以單獨擁有多個協程。
b. 線程程序都是同步機制,而協程則是異步。
c. 協程能保留上一次調用時的狀态,每次過程重入時,就相當于進入上一次調用的狀态。
d.線程是搶占式,而協程是非搶占式的,是以需要使用者自己釋放使用權來切換到其他協程,是以同一時間其實隻有一個協程擁有運作權,相當于單線程的能力。
e.協程并不是取代線程, 而且抽象于線程之上, 線程是被分割的CPU資源, 協程是組織好的代碼流程, 協程需要線程來承載運作, 線程是協程的資源, 但協程不會直接使用線程, 協程直接利用的是執行器(Interceptor), 執行器可以關聯任意線程或線程池, 可以使目前線程, UI線程, 或建立新程.。
f.線程是協程的資源。協程通過執行器來間接使用線程這個資源。
15.并發與并行
并發:計算機的作業系統通過時間片輪轉法等算法排程交替執行不同的任務。
并行:同時執行不同的任務。
16.同步與異步
同步:是指一個程序在執行某個請求的時候,若這個請求沒有執行完成,那麼這個程序将會一直等待下去,直到這個請求執行完畢,才會繼續執行下面的請求。
異步:是指一個程序在執行某個請求的時候,如果這個請求沒有執行完畢,程序不會等待,而是繼續執行下面的請求。
17.阻塞與非阻塞
阻塞:指調用函數時候目前線程被挂起
非堵塞:指調用函數時候目前線程不會被挂起,而是立即傳回。
18.互斥鎖
a. 線程鎖保證同一時刻隻有一個線程修改記憶體空間的同一資料,GIL保證同一時刻隻有一個線程在運作。
b. 多線程同時修改同一資料,可能會導緻資料最終結果不準确。
簡單總結
a. 程序是資源配置設定的機關
b. 線程是作業系統排程的機關
c. 程序切換需要的資源很最大,效率很低
d. 線程切換需要的資源一般,效率一般(當然了在不考慮GIL的情況下)
e. 協程切換任務資源很小,效率高
f. 多程序、多線程根據cpu核數不一樣可能是并行的,但g. 是協程是在一個線程中 是以是并發