目錄
-
第十五章、Python多線程之信號量和GIL
- 1. 信號量(Semaphore)
-
2. GIL
- 說明:
第十五章、Python多線程之信號量和GIL
1. 信號量(Semaphore)
信號量用來控制線程并發數的,Semaphore管理一個內置的計數 器,每當調用acquire()時-1,調用release()時+1。計數器不能小于0,當計數器為 0時,acquire()將阻塞線程至同步鎖定狀態,直到其他線程調用release()。其實就是控制最多幾個線程可以操作同享資源。
import threading
import time
semaphore = threading.Semaphore(5)
def func():
if semaphore.acquire():
print (threading.currentThread().getName() + '獲取共享資源')
time.sleep(2)
semaphore.release()
for i in range(10)
t1 = threading.Thread(target=func)
t1.start()
--------------------------------------------------
Thread-1獲取共享資源
Thread-2獲取共享資源
Thread-3獲取共享資源
Thread-4獲取共享資源
Thread-5獲取共享資源
Thread-6獲取共享資源
Thread-8獲取共享資源
Thread-7獲取共享資源
Thread-9獲取共享資源
Thread-10獲取共享資源
上面一個簡單的例子就是創建10個線程,讓每次只讓5個線程去執行func函數。
結果:5個線程一批一批的執行打印,中間停格2s
2. GIL
含義:全局解釋器鎖 。
作用:無論你啟多少個線程,你有多少個cpu, Python在執行的時候只會的在同一時刻只允許一個線程(線程之間有競爭)拿到GIL在一個cpu上運行,當線程遇到IO等待或到達者輪詢時間的時候,cpu會做切換,把cpu的時間片讓給其他線程執行,cpu切換需要消耗時間和資源,所以計算密集型的功能(比如加減乘除)不適合多線程,因為cpu線程切換太多,IO密集型比較適合多線程。
任務:
-
IO密集型(各個線程都會都各種的等待,如果有等待,線程切換是比較適合的),也可以采用可以用多進程+協程
-
計算密集型(線程在計算時沒有等待,這時候去切換,就是無用的切換),python不太適合開發這類功能
? 我們前面舉得例子里面模擬了sleep操作,其實就是相當于遇到IO,這種場景用多線程是可以增加性能的,但是如果我們用多線程來計算數據的計算,性能反而會降低。
證明一下:
from threading import Thread
from multiprocessing import Process
import time
#計算密集型
def work1():
res=0
for i in range(100000000): #1+8個0
res*=i
if __name__ == '__main__':
t_list = []
start = time.time()
for i in range(4):
# t = Thread(target=work1)
t = Process(target=work1)
t_list.append(t)
t.start()
for t in t_list:
t.join()
end = time.time()
# print('多線程',end-start) # 多線程 15.413789510726929
print('多進程',end-start) # 多進程 4.711405515670776
from threading import Thread
from multiprocessing import Process
import time
# io密集型
def work1():
x = 1+1
time.sleep(5)
if __name__ == '__main__':
t_list = []
start = time.time()
for i in range(4):
t = Thread(target=work1)
# t = Process(target=work1)
t_list.append(t)
t.start()
for t in t_list:
t.join()
end = time.time()
print('多線程',end-start) # 多線程 5.002625942230225
# print('多進程',end-start) # 多進程 5.660863399505615
說明:
在Cpython解釋器中有一把GIL鎖(全局解釋器鎖),GIl鎖本質是一把互斥鎖。
導致了同一個進程下,同一時間只能運行一個線程,無法利用多核優勢.
同一個進程下多個線程只能實現并發不能實現并行.
為什么要有GIL?
因為cpython自帶的垃圾回收機制不是線程安全的,所以要有GIL鎖.
導致了同一個進程下,同一時間只能運行一個線程,無法利用多核優勢.
分析:我們有四個任務需要處理,處理方式肯定是要玩出并發的效果,解決方案可以是:
方案一:開啟四個進程
方案二:一個進程下,開啟四個線程
計算密集型 推薦使用多進程
每個都要計算10s
多線程
在同一時刻只有一個線程會被執行,也就意味著每個10s都不能省,分開每個都要計算10s,共40.ns
多進程
可以并行的執行多個線程,10s+開啟進程的時間
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
