1. 程式人生 > >GIL 相關 和進程池

GIL 相關 和進程池

多線程 == 自己的 自己 process 多個 python 區別 舉例

#GIL  (global interpreter Lock)

#全局解釋器鎖 :鎖是為了避免資源競爭造成數據錯亂

#當一個py啟動後 會先執行主線程中的代碼
#在以上代碼中有啟動了子線程 子線程的任務還是執行代碼
#解釋器在一個進程中只有一個(解釋器也是一堆代碼)
#主線和子線都要去調用解釋器,就存在了競爭關系



#全局解釋器鎖: 是為了防止多個線程同時使用python解釋器 一旦加鎖 將導致線程無法並行
#這個問題不是所有解釋器都存在 只有cpython(c寫的解釋器) 也就是說只有cpythonzhong
#有全局解釋器鎖 如果是Jpython 就要參考Java的多線程實現
#python程序的執行:
#1.啟動解釋器進程 python.exe
#2.解析py文件並執行它

# 每個py程序中都必須有解釋器參與 解釋器其實就是一堆代碼
#相當於多個線程要調用同一個解釋器代碼 共享變成競爭 競爭就要出事 給解釋器加互斥鎖

# python中內存管理依賴於GC(一段用於回收內存的代碼) 也需要一個線程 除了自己開的線
# 程 系統還有一些內置線程 就算你的代碼不會去競爭解釋器 內置線程也可能會競爭 所以
# 所以必須加上鎖

#當一個線程遇到了IO 同時解釋器也會自動解鎖 去執行其他線程 cpu會切換到其他程序
# 案例:
# from threading import Thread
# import time
# def task1():
# sum=1
# for i in range(10000000):
# sum+=i
# def task2():
# sum=1
# for i in range(10000000):
# sum+=i
# start=time.time()
# t1=Thread(target=task1)
# t2=Thread(target=task2)
# t1.start()
# t2.start()
# t1.join()
# t2.join()
# print(time.time()-start)

#解釋器加鎖以後:
#將導致所有線程只能並發 不能達到真正的並行 意味著同意時間只有一個cpu在處理你的
#線程 給你的感覺是小路低

#代碼執行有兩種狀態;
#阻塞 i/o :失去cpu的執行權 (cpu等待I/O完成)
#非阻塞 :代碼正常執行 比如循環一千萬次 中途cpu可能切換 但是很快會回來(cpu在計算)

#加入有32核cpu 要處理一個下載任務 網絡速度慢 100k/s 文件大小為1024kb 如果你的代碼中
#IO操作非常多 cpu性能不能直接決定你的任務處理速度

#案例:
#目前有三個任務 每個任務處理需要一秒 獲取元數據需要一小時
#3個cpu 需要一小時一秒
#1個cpu 需要一小時三秒

#在IO密集的程序中 cpu性能無法直接決定程序的執行速度 python就應該幹這種活兒
#在計算密集的程序中 cpu性能可以直接決定程序的執行效率



#2.GIL與互斥鎖
#GIL與互斥鎖:
# from threading import Thread,Lock
# import time
# mutex=Lock()
# num = 1
# def task():
# global num
# mutex.acquire()
# temp=num
# time.sleep(1) #當線程中出現io時 GIL鎖就解開了
# num=temp+1
# mutex.release()
# t1=Thread(target=task,)
# t2=Thread(target=task,)
# t1.start()
# t2.start()
# t1.join()
# t2.join()
# print(num)
# #GIL和自定義互斥鎖的區別
# #全局鎖不能保證自己的線程安全 但是保證解釋器中的數據安全
# #GIL在線程調用解釋器時 自動加鎖 IO阻塞時和線程代碼執行完畢時 自動解鎖
#
#3.線程池與進程池
# 進程池: 就是一個裝進程的容器
# 為什麽出現: 當進程很多的時候方便管理進程
# 什麽時候用:當並發量特別大的時候 例如雙十一 很多時候進程是空閑的 就讓他進入進程池
#讓有任務處理的進程進入進程池
# 進程池:
# ProcessPoolExecutor
# 創建時指定最大進程數 自動創建進程
# 調用submit函數將任務提交到進程池中
# 創建進程是在調用submit後發生的
#舉例:
# #收發數據
# def task(c,addr):
# while True:
# data=c.recv(1024)
# print(data.decode("utf-8"))
# if not data:
# c.close()
# break
# c.send(data.upper())
# if __name__ == ‘__main__‘:
# import socket
# from concurrent.futures import ProcessPoolExecutor
# server=socket.socket()
# server.bind(("127.0.0.1",8091))
# server.listen(5)
# #創建一個進程池 默認
# pool=ProcessPoolExecutor()
# while True:
# c,addr = server.accept()
# pool.submit(task,c,addr)

#總結一下:
# 進程池可以自動創建進程
# 進程限制最大進程數
# 自動選擇一個空閑的進程幫你處理任務

GIL 相關 和進程池