網站首頁 編程語言 正文
引言
我們經常聽到"因為GIL的存在,python的多線程不能利用多核CPU",現在我們暫且不提GIL,python能不能利用多核cpu,今天我做了一個實驗,代碼很簡單如下所示
while 1:
pass
沒有運行這段代碼前cpu狀態
運行之后的狀態
下面兩張圖是運行之后的狀態,當然這只是兩張比較有代表性的圖,截圖間隔有十幾秒的樣子
根據第一張圖我們發現cpu1、cpu3的負載有明顯增長,我們可以得出python線程是可以利用多核cpu的結論,之前一直以為python運行后會綁定cpu其中的一個核心現在看來并不是這個樣子。第二張圖就比較有意思了cpu2滿載了,這又是為什么呢?
想來想去應該是linux中cpu對進程的親和性導致的,這種親和性是軟性的并不是強制的,這也就解釋了為什么第一張圖中是多cpu在負載。
ok為了更直觀的看出python線程能夠利用多核cpu,我們改下代碼,換一種方式再來看下
import os
while 1:
print os.getpid() # 輸出進程號
運行代碼結果
一目了然,線程的確在不同的核心上切換。
現在我們回過頭看下那句經典的話"因為GIL的存在,python的多線程不能利用多核CPU",這句話很容易讓人理解成GIL會讓python在一個核心上運行,有了今天的例子我們再來重新理解這句話,GIL的存在讓python在同一時刻只能有一個線程在運行,這毋庸置疑,但是它并沒有給線程鎖死或者說指定只能在某個cpu上運行,另外我需要說明一點的是GIL是與進程對應的,每個進程都有一個GIL。
python線程的執行流程理解
線程 ——>搶GIL——>CPU
這種執行流程導致了CPU密集型的多線程程序雖然能夠利用多核cpu時跟單核cpu是差不多的,并且由于多個線程搶GIL這個環節導致運行效率<=單線程。
看到這可能會讓人產生一種錯覺,有了GIL后python是線程安全的,好像根本不需要線程鎖,而實際情況是線程拿到CPU資源后并不是一直執行的,python解釋器在執行了該線程100條字節碼(注意是字節碼不是代碼)時會釋放掉該線程的GIL,如果這時候沒有加鎖那么其他線程就可能修改該線程用到的資源;
遇到IO也會釋放GIL
另外一個問題是遇到IO也會釋放GIL,下面是這兩種情況的例子
import threading
a = []
def m1():
for _ in range(100000):
a.append(1)
def m2():
for _ in range(100000):
a.append(2)
def check():
"""
檢查a是否有序
"""
for i in range(len(a)):
if i != 0:
if a[i] < a[i-1]:
print a[i-1], a[i]
return False
return True
t1 = threading.Thread(target=m1)
t2 = threading.Thread(target=m2)
t1.start()
t2.start()
t1.join()
t2.join()
print check()
預期1111...22222...,截圖顯示跟預期的不同
import threading
text1 = '1' * 10000
text2 = '2' * 10000
def write(text):
with open('test.txt', 'a') as f:
f.write(text)
def m1():
write(text1)
def m2():
write(text2)
t1 = threading.Thread(target=m1)
t2 = threading.Thread(target=m2)
t1.start()
t2.start()
t1.join()
t2.join()
test.txt截圖
最后結論是,因為GIL的存在,python的多線程雖然可以利用多核CPU,但并不能讓多個核同時工作。
原文鏈接:https://www.jianshu.com/p/48dfd429525d
相關推薦
- 2022-06-19 Visual?Studio創建WPF項目_實用技巧
- 2022-11-19 如何使用?Go?和?Excelize?構建電子表格_Golang
- 2023-10-16 微信小程序瀏覽docx,pdf等文件在線預覽使用wx.openDocument
- 2022-04-28 web.xml中Maven占位符不生效問題記錄分析_web2.0
- 2022-06-30 Unity多屏幕設置的具體方案_C#教程
- 2023-11-13 【云原生】python獲取docker stats 容器cpu使用率
- 2023-03-27 Android三種雙屏異顯實現方法介紹_Android
- 2022-01-07 event的srcelement和target
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支