溫馨提示×

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

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

Python主線程與子線程的區(qū)別是什么

發(fā)布時(shí)間:2021-07-05 16:57:57 來(lái)源:億速云 閱讀:583 作者:Leah 欄目:編程語(yǔ)言

Python主線程與子線程的區(qū)別是什么,針對(duì)這個(gè)問(wèn)題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問(wèn)題的小伙伴找到更簡(jiǎn)單易行的方法。

Python子線程在創(chuàng)建自身的線程狀態(tài)對(duì)象后,會(huì)通過(guò)_PyGILState_NoteThreadState這個(gè)語(yǔ)句將這個(gè)對(duì)象放入到線程狀態(tài)對(duì)象鏈表中,當(dāng)前活動(dòng)的Python子線程不一定是獲得了GIL的線程。

在thread1.py中主線程現(xiàn)在是獲得了GIL的,但是子線程到現(xiàn)在還沒(méi)有申請(qǐng)GIL,自然也不會(huì)將自身掛起。由于主線程和子線程都是Win32的原生線程。所以操作系統(tǒng)可能在主線程和Python子線程之間切換。我們?cè)谶@里要著重指出操作系統(tǒng)級(jí)的線程調(diào)度和Python級(jí)的線程調(diào)度是不同的。

Python級(jí)的線程調(diào)度一定意味著GIL擁有權(quán)的易手,而操作系統(tǒng)級(jí)的線程調(diào)度并不一定意味著GIL的易手,當(dāng)所有的線程都完成了初始化動(dòng)作之后。操作系統(tǒng)的線程調(diào)度和Python的線程調(diào)度才會(huì)同一。那時(shí),Python的線程調(diào)度會(huì)迫使當(dāng)前活動(dòng)線程釋放GIL,而這一操作會(huì)觸發(fā)GIL中維護(hù)的Event內(nèi)核對(duì)象。

這個(gè)觸發(fā)又進(jìn)而觸發(fā)操作系統(tǒng)的線程調(diào)度。而在線程的初始化完成之前,在Python線程調(diào)度和操作系統(tǒng)線程調(diào)度之間并沒(méi)有這樣的因果關(guān)系。顯示了GIL在Python級(jí)線程調(diào)度與操作系統(tǒng)級(jí)線程調(diào)度之間所起的橋梁作用。

前面我們已經(jīng)剖析過(guò)PyEval_AcquireThread的代碼,在PyEval_AcquireThread中,子線程進(jìn)行了***的沖刺,它要生存,要執(zhí)行,于是它開(kāi)始通過(guò)PyThread_acquire_ lock爭(zhēng)取GIL。到了這一步。

Python子線程將自己掛起,操作系統(tǒng)的線程調(diào)度機(jī)制再也不能靠自身的力量將其喚醒,只有等待Python的線程調(diào)度機(jī)制強(qiáng)迫主線程放棄GIL后。子線程才會(huì)被喚醒;而子線程被喚醒之后,主線程卻又陷入了苦苦地等待中,同樣苦苦地守望著Python強(qiáng)迫子線程放棄GIL的那一刻。

當(dāng)子線程被Python的線程調(diào)度機(jī)制喚醒之后,它所作的***件事就是通過(guò)PyThreadState_Swap將Python維護(hù)的當(dāng)前線程狀態(tài)對(duì)象設(shè)置為其自身的狀態(tài)對(duì)象,一如操作系統(tǒng)的進(jìn)程上下文環(huán)境恢復(fù)一樣。

現(xiàn)在我們的Python子線程開(kāi)始等待GIL,但是注意,線程的初始化還沒(méi)有真正完成,因?yàn)?span >子線程還沒(méi)有順利進(jìn)入字節(jié)碼解釋器。當(dāng)Python線程調(diào)度將子線程喚醒之后。子線程將回到t_bootstrap中。

并進(jìn)入PyEval_CallObjectWithKeywords,從這里一直往前,最終將調(diào)用PyEval_EvalFrameEx,進(jìn)入解釋器。到了那個(gè)時(shí)候,Python子線程和主線程一樣,就完全被Python線程調(diào)度機(jī)制所控制了。

Python主線程與子線程的區(qū)別是什么

需要注意的是,PyThread_start_new_thread是在主線程中執(zhí)行的,而從bootstrap開(kāi)始,則是在子線程中執(zhí)行的。其中涉及線程銷(xiāo)毀的動(dòng)作,如PyThreadState_ DeleteCurrent等,將在后續(xù)的部分剖析。到了這里,讀者可能有些疑惑了,我們花費(fèi)了大量篇幅剖析的線程狀態(tài)對(duì)象鏈表似乎沒(méi)有什么用啊。其實(shí)不然,試想一下,當(dāng)線程調(diào)度發(fā)生時(shí)。

關(guān)于Python主線程與子線程的區(qū)別是什么問(wèn)題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒(méi)有解開(kāi),可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識(shí)。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI