中文字幕免费精品_亚洲视频自拍_亚洲综合国产激情另类一区_色综合咪咪久久

在Python下嘗試多線程編程
來源:易賢網 閱讀:914 次 日期:2015-04-30 14:26:39
溫馨提示:易賢網小編為您整理了“在Python下嘗試多線程編程”,方便廣大網友查閱!

這篇文章主要介紹了在Python下多線程編程的嘗試,由于GIL的存在,多線程在Python開發領域一直是個熱門問題,需要的朋友可以參考下

多任務可以由多進程完成,也可以由一個進程內的多線程完成。

我們前面提到了進程是由若干線程組成的,一個進程至少有一個線程。

由于線程是操作系統直接支持的執行單元,因此,高級語言通常都內置多線程的支持,Python也不例外,并且,Python的線程是真正的Posix Thread,而不是模擬出來的線程。

Python的標準庫提供了兩個模塊:thread和threading,thread是低級模塊,threading是高級模塊,對thread進行了封裝。絕大多數情況下,我們只需要使用threading這個高級模塊。

啟動一個線程就是把一個函數傳入并創建Thread實例,然后調用start()開始執行:

import time, threading

# 新線程執行的代碼:

def loop():

print 'thread %s is running...' % threading.current_thread().name

n = 0

while n < 5:

n = n + 1

print 'thread %s >>> %s' % (threading.current_thread().name, n)

time.sleep(1)

print 'thread %s ended.' % threading.current_thread().name

print 'thread %s is running...' % threading.current_thread().name

t = threading.Thread(target=loop, name='LoopThread')

t.start()

t.join()

print 'thread %s ended.' % threading.current_thread().name

執行結果如下:

thread MainThread is running...

thread LoopThread is running...

thread LoopThread >>> 1

thread LoopThread >>> 2

thread LoopThread >>> 3

thread LoopThread >>> 4

thread LoopThread >>> 5

thread LoopThread ended.

thread MainThread ended.

由于任何進程默認就會啟動一個線程,我們把該線程稱為主線程,主線程又可以啟動新的線程,Python的threading模塊有個current_thread()函數,它永遠返回當前線程的實例。主線程實例的名字叫MainThread,子線程的名字在創建時指定,我們用LoopThread命名子線程。名字僅僅在打印時用來顯示,完全沒有其他意義,如果不起名字Python就自動給線程命名為Thread-1,Thread-2……

Lock

多線程和多進程最大的不同在于,多進程中,同一個變量,各自有一份拷貝存在于每個進程中,互不影響,而多線程中,所有變量都由所有線程共享,所以,任何一個變量都可以被任何一個線程修改,因此,線程之間共享數據最大的危險在于多個線程同時改一個變量,把內容給改亂了。

來看看多個線程同時操作一個變量怎么把內容給改亂了:

import time, threading

# 假定這是你的銀行存款:

balance = 0

def change_it(n):

# 先存后取,結果應該為0:

global balance

balance = balance + n

balance = balance - n

def run_thread(n):

for i in range(100000):

change_it(n)

t1 = threading.Thread(target=run_thread, args=(5,))

t2 = threading.Thread(target=run_thread, args=(8,))

t1.start()

t2.start()

t1.join()

t2.join()

print balance

我們定義了一個共享變量balance,初始值為0,并且啟動兩個線程,先存后取,理論上結果應該為0,但是,由于線程的調度是由操作系統決定的,當t1、t2交替執行時,只要循環次數足夠多,balance的結果就不一定是0了。

原因是因為高級語言的一條語句在CPU執行時是若干條語句,即使一個簡單的計算:

balance = balance + n

也分兩步:

計算balance + n,存入臨時變量中;

將臨時變量的值賦給balance。

也就是可以看成:

x = balance + n

balance = x

由于x是局部變量,兩個線程各自都有自己的x,當代碼正常執行時:

初始值 balance = 0

t1: x1 = balance + 5 # x1 = 0 + 5 = 5

t1: balance = x1 # balance = 5

t1: x1 = balance - 5 # x1 = 5 - 5 = 0

t1: balance = x1 # balance = 0

t2: x2 = balance + 8 # x2 = 0 + 8 = 8

t2: balance = x2 # balance = 8

t2: x2 = balance - 8 # x2 = 8 - 8 = 0

t2: balance = x2 # balance = 0

結果 balance = 0

但是t1和t2是交替運行的,如果操作系統以下面的順序執行t1、t2:

初始值 balance = 0

t1: x1 = balance + 5 # x1 = 0 + 5 = 5

t2: x2 = balance + 8 # x2 = 0 + 8 = 8

t2: balance = x2 # balance = 8

t1: balance = x1 # balance = 5

t1: x1 = balance - 5 # x1 = 5 - 5 = 0

t1: balance = x1 # balance = 0

t2: x2 = balance - 5 # x2 = 0 - 5 = -5

t2: balance = x2 # balance = -5

結果 balance = -5

究其原因,是因為修改balance需要多條語句,而執行這幾條語句時,線程可能中斷,從而導致多個線程把同一個對象的內容改亂了。

兩個線程同時一存一取,就可能導致余額不對,你肯定不希望你的銀行存款莫名其妙地變成了負數,所以,我們必須確保一個線程在修改balance的時候,別的線程一定不能改。

如果我們要確保balance計算正確,就要給change_it()上一把鎖,當某個線程開始執行change_it()時,我們說,該線程因為獲得了鎖,因此其他線程不能同時執行change_it(),只能等待,直到鎖被釋放后,獲得該鎖以后才能改。由于鎖只有一個,無論多少線程,同一時刻最多只有一個線程持有該鎖,所以,不會造成修改的沖突。創建一個鎖就是通過threading.Lock()來實現:

balance = 0

lock = threading.Lock()

def run_thread(n):

for i in range(100000):

# 先要獲取鎖:

lock.acquire()

try:

# 放心地改吧:

change_it(n)

finally:

# 改完了一定要釋放鎖:

lock.release()

當多個線程同時執行lock.acquire()時,只有一個線程能成功地獲取鎖,然后繼續執行代碼,其他線程就繼續等待直到獲得鎖為止。

獲得鎖的線程用完后一定要釋放鎖,否則那些苦苦等待鎖的線程將永遠等待下去,成為死線程。所以我們用try...finally來確保鎖一定會被釋放。

鎖的好處就是確保了某段關鍵代碼只能由一個線程從頭到尾完整地執行,壞處當然也很多,首先是阻止了多線程并發執行,包含鎖的某段代碼實際上只能以單線程模式執行,效率就大大地下降了。其次,由于可以存在多個鎖,不同的線程持有不同的鎖,并試圖獲取對方持有的鎖時,可能會造成死鎖,導致多個線程全部掛起,既不能執行,也無法結束,只能靠操作系統強制終止。

多核CPU

如果你不幸擁有一個多核CPU,你肯定在想,多核應該可以同時執行多個線程。

如果寫一個死循環的話,會出現什么情況呢?

打開Mac OS X的Activity Monitor,或者Windows的Task Manager,都可以監控某個進程的CPU使用率。

我們可以監控到一個死循環線程會100%占用一個CPU。

如果有兩個死循環線程,在多核CPU中,可以監控到會占用200%的CPU,也就是占用兩個CPU核心。

要想把N核CPU的核心全部跑滿,就必須啟動N個死循環線程。

試試用Python寫個死循環:

import threading, multiprocessing

def loop():

x = 0

while True:

x = x ^ 1

for i in range(multiprocessing.cpu_count()):

t = threading.Thread(target=loop)

t.start()

啟動與CPU核心數量相同的N個線程,在4核CPU上可以監控到CPU占用率僅有160%,也就是使用不到兩核。

即使啟動100個線程,使用率也就170%左右,仍然不到兩核。

但是用C、C++或Java來改寫相同的死循環,直接可以把全部核心跑滿,4核就跑到400%,8核就跑到800%,為什么Python不行呢?

因為Python的線程雖然是真正的線程,但解釋器執行代碼時,有一個GIL鎖:Global Interpreter Lock,任何Python線程執行前,必須先獲得GIL鎖,然后,每執行100條字節碼,解釋器就自動釋放GIL鎖,讓別的線程有機會執行。這個GIL全局鎖實際上把所有線程的執行代碼都給上了鎖,所以,多線程在Python中只能交替執行,即使100個線程跑在100核CPU上,也只能用到1個核。

GIL是Python解釋器設計的歷史遺留問題,通常我們用的解釋器是官方實現的CPython,要真正利用多核,除非重寫一個不帶GIL的解釋器。

所以,在Python中,可以使用多線程,但不要指望能有效利用多核。如果一定要通過多線程利用多核,那只能通過C擴展來實現,不過這樣就失去了Python簡單易用的特點。

不過,也不用過于擔心,Python雖然不能利用多線程實現多核任務,但可以通過多進程實現多核任務。多個Python進程有各自獨立的GIL鎖,互不影響。

小結

多線程編程,模型復雜,容易發生沖突,必須用鎖加以隔離,同時,又要小心死鎖的發生。

Python解釋器由于設計時有GIL全局鎖,導致了多線程無法利用多核。多線程的并發在Python中就是一個美麗的夢。

更多信息請查看IT技術專欄

更多信息請查看網絡編程
易賢網手機網站地址:在Python下嘗試多線程編程
由于各方面情況的不斷調整與變化,易賢網提供的所有考試信息和咨詢回復僅供參考,敬請考生以權威部門公布的正式信息和咨詢為準!

2026上岸·考公考編培訓報班

  • 報班類型
  • 姓名
  • 手機號
  • 驗證碼
關于我們 | 聯系我們 | 人才招聘 | 網站聲明 | 網站幫助 | 非正式的簡要咨詢 | 簡要咨詢須知 | 新媒體/短視頻平臺 | 手機站點 | 投訴建議
工業和信息化部備案號:滇ICP備2023014141號-1 云南省教育廳備案號:云教ICP備0901021 滇公網安備53010202001879號 人力資源服務許可證:(云)人服證字(2023)第0102001523號
云南網警備案專用圖標
聯系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關注公眾號:hfpxwx
咨詢QQ:1093837350(9:00—18:00)版權所有:易賢網
云南網警報警專用圖標
中文字幕免费精品_亚洲视频自拍_亚洲综合国产激情另类一区_色综合咪咪久久
亚洲人成人一区二区在线观看| 狠狠狠色丁香婷婷综合久久五月| 在线免费观看欧美| 欧美伊人久久久久久久久影院| 9色国产精品| 9久re热视频在线精品| 一区二区三区久久久| 亚洲视频国产视频| 午夜影视日本亚洲欧洲精品| 久久爱另类一区二区小说| 欧美一区免费视频| 久久免费视频网站| 免费成人黄色片| 欧美日韩午夜视频在线观看| 国产精品亚洲综合一区在线观看| 好男人免费精品视频| 亚洲狼人精品一区二区三区| 久久精品30| 欧美精品国产精品日韩精品| 国产精品综合色区在线观看| 亚洲国产裸拍裸体视频在线观看乱了中文| 亚洲在线国产日韩欧美| 欧美激情视频免费观看| 亚洲第一精品影视| 久久精品伊人| 国产日韩欧美综合精品| 亚洲一区二区精品在线观看| 欧美激情一区二区在线| 亚洲观看高清完整版在线观看| 欧美在线视频观看| 国产精品久久久久久av福利软件 | 国产精品99久久久久久久女警 | 国产精品卡一卡二卡三| 最新精品在线| 免费高清在线一区| 怡红院av一区二区三区| 久久精品理论片| 国产日韩欧美亚洲一区| 国产精品分类| 日韩亚洲国产欧美| 欧美大片18| 国产视频在线观看一区二区三区 | 欧美暴力喷水在线| 欧美日韩情趣电影| 最新日韩在线视频| 狂野欧美激情性xxxx欧美| 国产亚洲精品久久久久动| 亚洲欧美日产图| 国产精品v欧美精品∨日韩| 亚洲国产欧美一区| 国产毛片精品视频| 99精品国产福利在线观看免费 | 国产精品爱啪在线线免费观看| 亚洲欧洲中文日韩久久av乱码| 久久久久久久网| 激情亚洲网站| 老巨人导航500精品| 欧美日韩一区在线视频| 一区视频在线播放| 久久一综合视频| 亚洲电影中文字幕| 欧美高清视频一区二区| 日韩亚洲欧美一区二区三区| 欧美日产一区二区三区在线观看| 亚洲精品一区在线观看| 欧美色偷偷大香| 亚洲欧美成人在线| 国产午夜精品久久久久久免费视| 欧美一站二站| 在线观看亚洲精品| 欧美精品高清视频| 国产精品99久久久久久白浆小说| 国产精品视屏| 欧美久久久久久久| 国产日韩欧美亚洲| 久久高清国产| 亚洲经典在线看| 亚洲一二三区在线观看| 一区在线观看视频| 欧美性视频网站| 亚洲一区二区免费视频| 国产欧美日韩一区二区三区| 精品99一区二区| 欧美aⅴ99久久黑人专区| 亚洲人屁股眼子交8| 欧美午夜免费| 久久精品国产亚洲5555| 亚洲精品视频一区二区三区| 国产精品v欧美精品v日本精品动漫 | 亚洲精品国产无天堂网2021| 欧美日韩视频在线一区二区 | 国产精品扒开腿爽爽爽视频| 欧美在线视频一区二区三区| 亚洲国产精品小视频| 欧美性猛片xxxx免费看久爱 | 欧美一区二区在线播放| 韩国一区二区三区美女美女秀| 欧美成人一二三| 国产情人综合久久777777| 国产精品久久久久久久久免费桃花| 国产精品久久久久久久久久久久| 欧美欧美午夜aⅴ在线观看| 一区二区三区在线免费视频| 在线视频欧美一区| 久久久久久夜| 国产精品www色诱视频| 亚洲国产美女| 亚洲一区免费| 久久亚洲视频| 国产亚洲综合在线| 国产精品r级在线| 久久亚洲私人国产精品va媚药| 一区二区欧美视频| 精品1区2区3区4区| 国产精品美女久久| 欧美精品在线免费播放| 久久夜色精品| 精品51国产黑色丝袜高跟鞋| 欧美性生交xxxxx久久久| 日韩一级大片| 99视频精品在线| 国产欧美激情| 日韩西西人体444www| 欧美日韩一本到| 欧美一级网站| 国产精品视频精品| 日韩天天综合| 欧美精品导航| 一本到高清视频免费精品| 欧美伊人精品成人久久综合97| 欧美视频在线播放| 亚洲欧美一区二区三区久久 | 国产欧美一二三区| 亚洲精品欧美日韩| 国产日韩成人精品| 久久夜色精品| 一片黄亚洲嫩模| 国产欧美精品va在线观看| 黄色精品一区| 欧美日韩精品高清| 国产精品一卡二卡| 老司机免费视频一区二区| 老司机午夜精品视频| 欧美一区二区三区免费看| 亚洲精品综合精品自拍| 日韩视频在线永久播放| 久久精品国产免费| 欧美午夜一区二区| 一本色道久久综合狠狠躁篇的优点 | 国产欧美一区二区精品忘忧草| 国内精品免费午夜毛片| 亚洲最新在线| 欧美激情国产日韩精品一区18| 国产日产欧美一区| 久久精品国产清高在天天线| 欧美精品不卡| 99国产精品久久久久久久成人热| 免费久久精品视频| 日韩亚洲在线| 国产婷婷色一区二区三区在线 | 亚洲精品久久久久久久久久久| 欧美综合激情网| 国产精品理论片| 日韩视频在线一区| 欧美激情无毛| 99re6这里只有精品| 久久久免费精品| 国产精品久久久久91| 亚洲国产91| 免费成人黄色| 亚洲福利专区| 久久久夜精品| 最新高清无码专区| 欧美精品一区二| 一本综合精品| 国产精品成人国产乱一区| 亚洲一区影音先锋| 国产精品福利在线| 亚洲一区二区在线免费观看| 欧美日韩一区二区免费在线观看| 亚洲精品中文字幕有码专区| 欧美成人精品1314www| 亚洲美女电影在线| 欧美日韩在线观看一区二区| 亚洲午夜一区二区三区| 国产嫩草影院久久久久| 久久成年人视频| 91久久精品国产91久久性色| 欧美日韩精品欧美日韩精品一| 亚洲视频在线观看免费| 国产欧美亚洲视频| 美女尤物久久精品| 亚洲女与黑人做爰| 亚洲丁香婷深爱综合| 国产精品大全| 免费成人小视频| 欧美一区二区三区视频免费播放| 韩国三级电影久久久久久| 免费在线播放第一区高清av| 亚洲午夜女主播在线直播|