1. 程式人生 > >day33 執行緒的建立 驗證執行緒之間共享資料 守護執行緒 執行緒程序效率對比 鎖 死鎖 遞迴鎖

day33 執行緒的建立 驗證執行緒之間共享資料 守護執行緒 執行緒程序效率對比 鎖 死鎖 遞迴鎖

今日內容
1.執行緒理論

2.鎖: 犧牲了效率,保證了資料的安全(重點)

3.守護執行緒

4.GIL鎖:(重點)

5.計算密集型和IO密集型

6.訊號量,事件(瞭解)

 7.補充. 子程序中不能input

1.執行緒理論
什麼是執行緒:cpu的執行單位(實體)
程序: 資源分配單位
執行緒的建立和銷燬的開銷特別小

執行緒之間的資源共享,共享的是同一個程序中的資源

資源的共享涉及的最主要的問題就是資料的安全問題,這裡我們就要用到加鎖來實現.

執行緒的2種建立方式
方法1:
from threading import Thread

def f1(n):
print(n)
if __name__=='__main__':
t=Thread(target=f1,args=(3,) )
t.start()

方法2:
class mythread(thread):
def __init__(self,n):
super().__init__()
self.n=n
def run(self):
print(f'{n}號種子選手.')

if __name__=='__main__':
m=mythread('alex')
m.start()

2.鎖: 犧牲了效率,保證了資料的安全(重點)
死鎖現象: 當程式程式碼中出現了鎖的巢狀,兩個程式相互爭搶拿鎖,導致一方拿到一把鎖,但是需要下一把鎖的時候,雙方都在等待對方開鎖,所以導致了死鎖的現象.

遞迴鎖:(重點推薦) 他可以解決死鎖的現象
import RLock 首先遞迴鎖本身就是一個互斥鎖,維護了一個計數器,每次acquire一次就加一,release一次就減一,當計數器的值為0的時候,剩下的程式才能繼續搶這個鎖.

3.守護執行緒: 等待所有的非守護執行緒結束時他直接結束. 如果守護執行緒之外的所有執行緒執行完畢後,守護執行緒直接完畢(守護執行緒已經執行了的部分也是會被列印的)
守護程序: 主程序的程式碼結束後,守護程序直接結束(不管運沒執行完畢).

import time
from threading import Thread
from multiprocessing import Process
def f1():
time.sleep(2)
print('1號執行緒')

def f2():
time.sleep(3)
print('2號執行緒')
if __name__ == '__main__':
# t1 = Thread(target=f1,)
# t2 = Thread(target=f2,)
# t1.daemon = True
# t2.daemon = True
# t1.start()
# t2.start()
# print('主執行緒結束')
t1 = Process(target=f1, )
t2 = Process(target=f2, )
# t1.daemon = True
# # t2.daemon = True
t1.start()
t2.start()

print('主程序結束'
4.GIL鎖:(重點)

GIL鎖: 全域性直譯器鎖,他的本身就是一個互斥鎖

直譯器內部程式不支援多個執行緒同時解釋

多個程序可以應用多核技術,因為每個程序裡面都有直譯器程式

這個圖的含義是程式碼可以有多個程序進入cpu去執行,但是一個程序裡面只允許有一個執行緒進入python直譯器中解釋.


原理: 首先硬碟接收到一個執行程序的資料,硬碟去記憶體開啟一個空間,然後程序中的n條程式碼去cpython直譯器中爭搶進入cpython 直譯器.由於直譯器中存在GIL鎖,所以只能有一條資料進入cpython直譯器中去執行程式碼.爭搶到的程式碼先到編譯器中編譯成c語言的位元組碼(.pyc檔案),然後到虛擬機器中轉化為2進位制檔案,最後虛擬機器將2進位制檔案傳送給cpu去執行這段程式碼.


5.計算密集型和IO密集型

計算密集型資料,
如果兩邊同時執行,這邊計算一點點,然後切換到另一遍計算一點點,也是可以的,但是再切換的同時切換也是會耗時間的,如果一個程式程式碼量很大,機器來回進行切換所耗的時間也是很長的.

IO密集型資料
這樣程式遇到了IO就進行切換,提高了程式碼的執行效率

6.訊號量,事件(瞭解)

7.補充. 子程序中不能input

from threading import Thread
from multiprocessing inport Process

def f1():
name=input('請輸入你的姓名:') # 子程式中不能使用input
print(name)

if __name__=='__main__':
input('請輸入你的資訊:') #主程式中可以使用input,
t=Thread(target=f1,)
t.start()
print('主程式結束')