溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

python中多線程指的是什么

發布時間:2020-09-03 10:59:59 來源:億速云 閱讀:249 作者:小新 欄目:編程語言

這篇文章主要介紹python中多線程指的是什么,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

1、多線程的理解

多進程和多線程都可以執行多個任務,線程是進程的一部分。線程的特點是線程之間可以共享內存和變量,資源消耗少(不過在Unix環境中,多進程和多線程資源調度消耗差距不明顯,Unix調度較快),缺點是線程之間的同步和加鎖比較麻煩。

2、Python多線程創建

在Python中,同樣可以實現多線程,有兩個標準模塊thread和threading,不過我們主要使用更高級的threading模塊。使用例子:

import threading
import time 
def target():
    print 'the curent threading  %s is running' % threading.current_thread().name
    time.sleep(1)
    print 'the curent threading  %s is ended' % threading.current_thread().name 
print 'the curent threading  %s is running' % threading.current_thread().name
t = threading.Thread(target=target) 
t.start()
t.join()
print 'the curent threading  %s is ended' % threading.current_thread().name

輸出:

the curent threading  MainThread is running
the curent threading  Thread-1 is running
the curent threading  Thread-1 is ended
the curent threading  MainThread is ended

start是啟動線程,join是阻塞當前線程,即使得在當前線程結束時,不會退出。從結果可以看到,主線程直到Thread-1結束之后才結束。

Python中,默認情況下,如果不加join語句,那么主線程不會等到當前線程結束才結束,但卻不會立即殺死該線程。如不加join輸出如下:

the curent threading  MainThread is running
the curent threading  Thread-1 is running
 the curent threading  MainThread is ended
the curent threading  Thread-1 is ended

但如果為線程實例添加t.setDaemon(True)之后,如果不加join語句,那么當主線程結束之后,會殺死子線程。代碼:

import threading
import time
def target():
    print 'the curent threading  %s is running' % threading.current_thread().name
    time.sleep(4)
    print 'the curent threading  %s is ended' % threading.current_thread().name
print 'the curent threading  %s is running' % threading.current_thread().name
t = threading.Thread(target=target)
t.setDaemon(True)
t.start()
t.join()
print 'the curent threading  %s is ended' % threading.current_thread().name

輸出如下:

the curent threading  MainThread is running
the curent threading  Thread-1 is runningthe curent threading  MainThread is ended

如果加上join,并設置等待時間,就會等待線程一段時間再退出:

import threading
import time
def target():
    print 'the curent threading  %s is running' % threading.current_thread().name
    time.sleep(4)
    print 'the curent threading  %s is ended' % threading.current_thread().name
print 'the curent threading  %s is running' % threading.current_thread().name
t = threading.Thread(target=target)
t.setDaemon(True)
t.start()
t.join(1)

輸出:

the curent threading  MainThread is running
the curent threading  Thread-1 is running
the curent threading  MainThread is ended

主線程等待1秒,就自動結束,并殺死子線程。如果join不加等待時間,t.join(),就會一直等待,一直到子線程結束,輸出如下:

the curent threading  MainThread is running
the curent threading  Thread-1 is running
the curent threading  Thread-1 is ended
the curent threading  MainThread is ended

3、線程鎖和ThreadLocal

(1)線程鎖

對于多線程來說,最大的特點就是線程之間可以共享數據,那么共享數據就會出現多線程同時更改一個變量,使用同樣的資源,而出現死鎖、數據錯亂等情況。

假設有兩個全局資源,a和b,有兩個線程thread1,thread2. thread1占用a,想訪問b,但此時thread2占用b,想訪問a,兩個線程都不釋放此時擁有的資源,那么就會造成死鎖。

對于該問題,出現了Lock。 當訪問某個資源之前,用Lock.acquire()鎖住資源,訪問之后,用Lock.release()釋放資源。

a = 3
lock = threading.Lock()
def target():
    print 'the curent threading  %s is running' % threading.current_thread().name
    time.sleep(4)
    global a
    lock.acquire()
    try:
        a += 3
    finally:
        lock.release()
    print 'the curent threading  %s is ended' % threading.current_thread().name
    print 'yes'

用finally的目的是防止當前線程無線占用資源。

(2)ThreadLocal

介紹完線程鎖,接下來出場的是ThreadLocal。當不想將變量共享給其他線程時,可以使用局部變量,但在函數中定義局部變量會使得在函數之間傳遞特別麻煩。ThreadLocal是非常牛逼的東西,它解決了全局變量需要枷鎖,局部變量傳遞麻煩的兩個問題。通過在線程中定義:

local_school = threading.local()

此時這個local_school就變成了一個全局變量,但這個全局變量只在該線程中為全局變量,對于其他線程來說是局部變量,別的線程不可更改。 

def process_thread(name):# 綁定ThreadLocal的student: local_school.student = name

這個student屬性只有本線程可以修改,別的線程不可以。代碼:

local = threading.local()
def func(name):
    print 'current thread:%s' % threading.currentThread().name
    local.name = name
    print "%s in %s" % (local.name,threading.currentThread().name)
t1 = threading.Thread(target=func,args=('haibo',))
t2 = threading.Thread(target=func,args=('lina',))
t1.start()
t2.start()
t1.join()
t2.join()

從代碼中也可以看到,可以將ThreadLocal理解成一個dict,可以綁定不同變量。

ThreadLocal用的最多的地方就是每一個線程處理一個HTTP請求,在Flask框架中利用的就是該原理,它使用的是基于Werkzeug的LocalStack。

4、Map實現多線程:

對于多線程的使用,我們經常是用thread來創建,比較繁瑣:

class MyThread(threading.Thread):
    def init(self):
        threading.Thread.init(self)
def run(self):
    lock.acquire()
    print threading.currentThread().getName()
    lock.release()
 
def build_worker(num):
    workers = []
    for t in range(num):
        work = MyThread()
        work.start()
        workers.append(work)
    return workers
def producer():
    threads = build_worker(4)
    for w in threads:
        w.join()
    print 'Done'

如果要創建更多的線程,那就要一一加到里面,操作麻煩,代碼可讀性也變差。在Python中,可以使用map函數簡化代碼。map可以實現多任務的并發,簡單示例:

urls = ['http://www.baidu.com','http://www.sina.com','http://www.qq.com']
results=map(urllib2.urlopen,urls)

map將urls的每個元素當做參數分別傳給urllib2.urlopen函數,并最后把結果放到results列表中,map 函數一手包辦了序列操作、參數傳遞和結果保存等一系列的操作。 其原理:

map函數負責將線程分給不同的CPU。

在 Python 中有個兩個庫包含了 map 函數:

multiprocessing 和它鮮為人知的子庫 multiprocessing.dummy。dummy 是 multiprocessing 模塊的完整克隆,唯一的不同在于 multiprocessing 作用于進程,而 dummy 模塊作用于線程。代碼:

import urllib2
from multiprocessing.dummy import Pool as ThreadPool
urls = ['http://www.baidu.com','http://www.sina.com','http://www.qq.com']
pool = ThreadPool()
results = pool.map(urllib2.urlopen,urls)
print results
pool.close()
pool.join()
print 'main ended'

pool = ThreadPool()創建了線程池,其默認值為當前機器 CPU 的核數,可以指定線程池大小,不是越多越好,因為越多的話,線程之間的切換也是很消耗資源的。

results = pool.map(urllib2.urlopen,urls) 該語句將不同的url傳給各自的線程,并把執行后結果返回到results中。

代碼清晰明了,巧妙得完成Threading模塊完成的功能。

5、Python多線程的缺陷:

上面說了那么多關于多線程的用法,但Python多線程并不能真正能發揮作用,因為在Python中,有一個GIL,即全局解釋鎖,該鎖的存在保證在同一個時間只能有一個線程執行任務,也就是多線程并不是真正的并發,只是交替得執行。假如有10個線程炮在10核CPU上,當前工作的也只能是一個CPU上的線程。

6、Python多線程的應用場景:

雖然Python多線程有缺陷,總被人說成是雞肋,但也不是一無用處,它很適合用在IO密集型任務中。I/O密集型執行期間大部分是時間都用在I/O上,如數據庫I/O,較少時間用在CPU計算上。因此該應用場景可以使用Python多線程,當一個任務阻塞在IO操作上時,我們可以立即切換執行其他線程上執行其他IO操作請求。

以上是python中多線程指的是什么的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女