最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python低層多線程接口_thread模塊的用法和特性

 更新時間:2024年10月03日 12:19:37   作者:V1ncent Chen  
這篇文章主要介紹了Python低層多線程接口_thread模塊的用法和特性,_thread是python標(biāo)準(zhǔn)庫中的一個低層多線程API,可以在進(jìn)程中啟動線程來處理任務(wù),并且提供了簡單的鎖機(jī)制來控制共享資源的同步訪問,本文就_thread模塊的用法和特性做個簡單的演示,需要的朋友可以參考下

一、進(jìn)程和線程的區(qū)別

并行(多任務(wù)處理)是現(xiàn)代操作系統(tǒng)的基本特性,一個程序可以同時處理很多任務(wù)而不被阻塞。多任務(wù)處理的基本方式有兩種:進(jìn)程分支和線程派生。

進(jìn)程分支就是從當(dāng)前進(jìn)程復(fù)制一個程序副本,程序中的內(nèi)存副本,文件描述符等都會被復(fù)制,子進(jìn)程改變一個全局對象只是修改本地的副本,不會影響到父進(jìn)程。常用在啟動獨(dú)立的程序。

線程派生和進(jìn)程分支類似,但是子線程依然在原進(jìn)程中運(yùn)行,所有的子線程都會共享進(jìn)程中的全局對象,相對于進(jìn)程分支,少了一個"復(fù)制"的操作,因此更加輕量化,且由于共享進(jìn)程對象,相當(dāng)于自帶了線程間的通信機(jī)制(進(jìn)程間的通信則需要借助管道,套接字,信號等外部工具)。常用在處理一些輕量級任務(wù)。

但這些共享對象的訪問可能出現(xiàn)沖突,_thread也提供了鎖機(jī)制來同步化對象訪問,例如修改一個對象時,先獲取鎖,完成后再釋放,這樣就可以保證任意時間點(diǎn),最多能有1個線程能修改這個共享對象,防止出現(xiàn)混亂。

二、_thread模塊的用法

_thread模塊中的start_new_thread可以開啟一個新的線程并運(yùn)行指定程序。

2.1 派生線程

當(dāng)程序啟動時,其實(shí)它就已經(jīng)啟動了一個線程,這個就是主線程。通過_thread.start_new_thread方法,傳入一個函數(shù)對象和一個參數(shù)元組,就可以開啟新線程來執(zhí)行所傳入的函數(shù)對象。簡單的演示如下:

import _thread as thread
def func(id):
    print('我是 {} 號子線程'.format(id))
for i in range(5):
    thread.start_new_thread(func,(i,))

上面代碼執(zhí)行示意圖如下:for循環(huán)執(zhí)行了5次start_new_thread,這會開啟5個線程,每個線程去執(zhí)行func函數(shù)。因?yàn)榫€程是并行的,所以輸出的順序并不是0,1,2,3,4而是混亂的。注意3,4號子線程打印出現(xiàn)了重疊,這是因?yàn)樗鼈児蚕硪粋€標(biāo)準(zhǔn)輸出流,而我們沒有做同步化訪問控制,因而它們同時打印輸出。

2.2 同步化訪問控制

由于子線程可以共享進(jìn)程中的資源,這既是一個優(yōu)勢(方便線程間通信),也帶來了共享資源訪問的問題,如果多個子線程同時修改一個共享資源,那么就容易出現(xiàn)沖突,例如上面的輸出重疊。

為了解決這類問題,_thread模塊中的allocate_lock方法提供了一個簡單的鎖機(jī)制來控制共享訪問,每次獲取共享資源時先獲取鎖,可以保證任何時間點(diǎn)最多只有1個線程可以訪問該資源。示例如下:

import _thread as thread
lock = thread.allocate_lock()    # 定義一個鎖
def func(id):
    with lock:    # 用上下文管理器自動控制鎖的獲取和釋放
        print('我是 {} 號子線程'.format(id))
for i in range(5):
    thread.start_new_thread(func,(i,))

with lock會自動管理鎖對象的獲取和釋放,默認(rèn)線程會一直等待直到鎖的獲取,如果想要更精細(xì)的控制可以使用下面的方式:

lock.acquire()    # 獲取鎖
print('我是 {} 號子線程'.format(id))
lock.release()    # 釋放鎖

lock.acquire()有2個可選的參數(shù):blocking=True代表無法獲取鎖時等待,blocking=False代表如無法立刻獲取鎖則返回。timeout=-1代表等待的秒數(shù)(-1代表無限等待),此參數(shù)只有在blocking設(shè)置為True時才能指定。

2.3 子線程的退出控制

_thread派生子線程后,如果主線程運(yùn)行完畢,而子線程依然在運(yùn)行中,那么所有子線程就會隨著主線程的退出而被終止。

我們在子進(jìn)程中增加一個sleep來模擬長時間任務(wù),讓其運(yùn)行時長超過主線程。將下面的代碼保存到一個thread1.py中,以一個獨(dú)立進(jìn)程啟動:

import _thread as thread, time
lock = thread.allocate_lock()    # 定義一個鎖
def func(id):
    time.sleep(id)    # 子線程會睡眠,運(yùn)行時長將超過主線程
    with lock:
        print('我是 {} 號子線程'.format(id))
for i in range(5):
    thread.start_new_thread(func,(i,))
print('主線程結(jié)束,退出...')    # 主線程退出時打印提示

可以看到,主線程打印了退出提示,但子線程卻沒有任何輸出,這是因?yàn)橹骶€程運(yùn)行的時間非常短,當(dāng)其退出時,所有子線程都終止了。這種情況顯然不是我們想看到的。示例圖如下:

2.3.1 通過sleep等待子線程運(yùn)行結(jié)束

為了解決上面的問題,一個簡單的解決方案可以在主線程中加一個sleep,讓其等待一段時間再退出,但這個時間我們只能預(yù)估。在上面的代碼基礎(chǔ)上,增加一個time.sleep(3),讓主線程退出前等待3秒,保存為thread2.py,再次執(zhí)行:

import _thread as thread, time
lock = thread.allocate_lock()    # 定義一個鎖
def func(id):
    time.sleep(id)    # 子線程會睡眠,運(yùn)行時長將超過主線程
    with lock:
        print('我是 {} 號子線程'.format(id))
for i in range(5):
    thread.start_new_thread(func,(i,))
time.sleep(3)    # 主線程等待3秒再退出
print('主線程結(jié)束,退出...')    # 主線程退出時打印提示

可以看到部分子進(jìn)程運(yùn)行完畢,但還有部分子進(jìn)程未完成,因此這種方法不是很準(zhǔn)確,雖然你可以給一個足夠長的時間來保證所有子進(jìn)程運(yùn)行結(jié)束,但如果進(jìn)程長時間不結(jié)束,也會占用系統(tǒng)資源。

2.3.2 通過鎖的狀態(tài)監(jiān)測子進(jìn)程結(jié)束

_thread.allocate_lock除了可以控制共享對象的訪問,還可以用來傳遞全局狀態(tài),下面定義了包含5把鎖的列表,每個子線程執(zhí)行完成后會去獲取其中對應(yīng)位置上的鎖,在主線程中通過lock.locked()來檢查是否所有的鎖都被獲取,當(dāng)所有鎖都被獲取時(代表所有子線程都結(jié)束),主線程退出。將下面代碼保存到thread3.py中,再次運(yùn)行:

import _thread as thread, time
lock = thread.allocate_lock()    # 定義一個鎖
exit_locks = [thread.allocate_lock() for I in range(5)]   # 定義一個列表,包含5把鎖,對應(yīng)稍后啟動的5個子線程
def func(id):
    time.sleep(id)    # 子線程會睡眠,運(yùn)行時長將超過主線程
    with lock:
        print('我是 {} 號子線程'.format(id))
    exit_locks[id].acquire()    # 執(zhí)行完成后獲取exit_locks中對應(yīng)位置的鎖
for i in range(5):
    thread.start_new_thread(func,(i,))
for lock in exit_locks:
    while not lock.locked(): pass    # lock.locked()檢測鎖是否已被獲取
print('主線程結(jié)束,退出...')    # 主線程退出時打印提示

測試時可以發(fā)現(xiàn),主線程會在所有子線程執(zhí)行完畢后立刻退出,即不會提前導(dǎo)致子線程終止,也不會推遲浪費(fèi)系統(tǒng)資源。

2.3.3 通過共享變量監(jiān)測子進(jìn)程結(jié)束

由于子線程可以共享進(jìn)程中的變量,因此子線程中對共享對象的修改在主線程也可以看到,我們可以將上面的鎖替換為簡單的變量,可以達(dá)到相同的效果,下面使用一個共享列表,通過在子線程中修改變量值傳遞狀態(tài),將下面代碼保存為thread4.py并執(zhí)行:

import _thread as thread, time
lock = thread.allocate_lock()    # 定義一個鎖
exit_flags = [False]*5   # 定義一個全局共享列表,包含5個布爾變量False
def func(id):
    time.sleep(id)    # 子線程會睡眠,運(yùn)行時長將超過主線程
    with lock:
        print('我是 {} 號子線程'.format(id))
    exit_flags[id] = True    # 執(zhí)行完成后將共享列表中對應(yīng)位置的值改為True
for i in range(5):
    thread.start_new_thread(func,(i,))
while False in exit_flags:pass    # 檢測列表中是否有False,如果全部為Ture,代表所有子線程執(zhí)行完畢
print('主線程結(jié)束,退出...')    # 主線程退出時打印提示

可以看到主線程會等待子線程執(zhí)行完畢后退出,這種方式相比上面可以節(jié)約鎖分配的資源,看上去也更加簡單。

以上即是_thread模塊的基本用法?;赺thread模塊還有高級的threading模塊,_threading模塊是基于類和對象的高級接口,并提供了額外的控制工具,例如threading.join()可以實(shí)現(xiàn)等待子進(jìn)程退出。

到此這篇關(guān)于Python低層多線程接口_thread模塊的用法和特性的文章就介紹到這了,更多相關(guān)Python低層多線程接口內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python處理session的方法整理

    Python處理session的方法整理

    這篇文章主要介紹了Python處理session的方法以及相關(guān)知識點(diǎn)總結(jié),有需要的朋友們學(xué)習(xí)下。
    2019-08-08
  • python模型性能ROC和AUC分析詳解

    python模型性能ROC和AUC分析詳解

    這篇文章主要為大家介紹了python模型性能ROC和AUC分析詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • python避免死鎖方法實(shí)例分析

    python避免死鎖方法實(shí)例分析

    這篇文章主要介紹了python避免死鎖方法,較為詳細(xì)的分析了死鎖的成因與避免形成死鎖的方法,需要的朋友可以參考下
    2015-06-06
  • python基于event實(shí)現(xiàn)線程間通信控制

    python基于event實(shí)現(xiàn)線程間通信控制

    這篇文章主要介紹了python基于event實(shí)現(xiàn)線程間通信控制,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-01-01
  • Django+simpleui實(shí)現(xiàn)文件上傳預(yù)覽功能(詳細(xì)過程)

    Django+simpleui實(shí)現(xiàn)文件上傳預(yù)覽功能(詳細(xì)過程)

    該文章詳細(xì)介紹了如何在Django框架中實(shí)現(xiàn)文件上傳、預(yù)覽和下載功能,并使用SimpleUI美化Django后臺界面,通過創(chuàng)建模型、表單、視圖和配置URL,實(shí)現(xiàn)了文件的存儲和管理,同時,文章還提到了配置媒體文件、創(chuàng)建模板以及在生產(chǎn)環(huán)境中的部署注意事項(xiàng),感興趣的朋友一起看看吧
    2025-02-02
  • Python 異步之如何保護(hù)任務(wù)免于取消詳解

    Python 異步之如何保護(hù)任務(wù)免于取消詳解

    這篇文章主要為大家介紹了Python 異步之如何保護(hù)任務(wù)免于取消示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • 使用Python-OpenCV消除圖像中孤立的小區(qū)域操作

    使用Python-OpenCV消除圖像中孤立的小區(qū)域操作

    這篇文章主要介紹了使用Python-OpenCV消除圖像中孤立的小區(qū)域操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-07-07
  • python中re.findall()?的使用案例

    python中re.findall()?的使用案例

    re.findall()?函數(shù)是?python?中正則表達(dá)式模塊(re)的一個重要函數(shù),它可以根據(jù)正則表達(dá)式搜索字符串,并返回匹配的字符串列表,這篇文章給大家介紹了python中re.findall()?的使用案例,感興趣的朋友跟隨小編一起看看吧
    2023-09-09
  • Python數(shù)據(jù)結(jié)構(gòu)與算法之圖的基本實(shí)現(xiàn)及迭代器實(shí)例詳解

    Python數(shù)據(jù)結(jié)構(gòu)與算法之圖的基本實(shí)現(xiàn)及迭代器實(shí)例詳解

    這篇文章主要介紹了Python數(shù)據(jù)結(jié)構(gòu)與算法之圖的基本實(shí)現(xiàn)及迭代器,結(jié)合實(shí)例形式詳細(xì)分析了數(shù)據(jù)結(jié)構(gòu)與算法中圖的實(shí)現(xiàn)及迭代器相關(guān)算法原理與操作技巧,需要的朋友可以參考下
    2017-12-12
  • Python中turtle庫的使用實(shí)例

    Python中turtle庫的使用實(shí)例

    這篇文章主要介紹了Python中turtle庫的使用實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-09-09

最新評論

株洲县| 鹿泉市| 双江| 桐梓县| 安吉县| 新丰县| 淮阳县| 宁海县| 通化县| 天气| 宣恩县| 阿城市| 梅州市| 黄梅县| 黔江区| 江川县| 梅州市| 夏邑县| 荔波县| 宜都市| 汉沽区| 汾西县| 田阳县| 弥渡县| 斗六市| 法库县| 三明市| 临沧市| 扎兰屯市| 南昌县| 永胜县| 若尔盖县| 星座| 安平县| 班玛县| 贡嘎县| 龙里县| 滨海县| 汤原县| 卓资县| 财经|