第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會(huì)有你想問的

Python的主線程在停止時(shí)是否會(huì)收集垃圾?

Python的主線程在停止時(shí)是否會(huì)收集垃圾?

瀟湘沐 2021-03-22 14:10:38
在多線程Python進(jìn)程中,我有許多非守護(hù)進(jìn)程線程,這是指即使在主線程退出/停止后仍使主進(jìn)程保持活動(dòng)狀態(tài)的線程。我非守護(hù)線程持有弱引用在主線程對(duì)某些對(duì)象,但是當(dāng)主線程結(jié)束(控制脫落的文件的底部),這些對(duì)象就不會(huì)出現(xiàn)被垃圾收集,我的弱引用finaliser回調(diào)別開火。我期望主線程被垃圾回收是錯(cuò)誤的嗎?我本來希望將線程局部變量釋放(即收集垃圾)...我錯(cuò)過了什么?配套材料pprint.pprint( threading.enumerate() )顯示主線程的輸出已停止,而其他士兵繼續(xù)使用。[<_MainThread(MainThread, stopped 139664516818688)>, <LDQServer(testLogIOWorkerThread, started 139664479889152)>, <_Timer(Thread-18, started 139663928870656)>, <LDQServer(debugLogIOWorkerThread, started 139664437925632)>, <_Timer(Thread-17, started 139664463103744)>, <_Timer(Thread-19, started 139663937263360)>, <LDQServer(testLogIOWorkerThread, started 139664471496448)>, <LDQServer(debugLogIOWorkerThread, started 139664446318336)>]而且由于總是有人詢問用例...我的網(wǎng)絡(luò)服務(wù)有時(shí)會(huì)錯(cuò)過實(shí)時(shí)期限(這在最壞的情況下會(huì)導(dǎo)致整個(gè)系統(tǒng)故障)。事實(shí)證明這是因?yàn)椋ㄖ匾模〥EBUG數(shù)據(jù)的日志記錄會(huì)在文件系統(tǒng)發(fā)脾氣時(shí)阻塞。因此,我正在嘗試改造許多已建立的專用日志記錄庫,以將阻塞的I / O推遲到工作線程中??杀氖?,已建立的使用模式是混合記錄并行事務(wù)的短期日志記錄通道和從未明確關(guān)閉的長期模塊作用域通道的混合。因此,我創(chuàng)建了一個(gè)裝飾器,該裝飾器將對(duì)方法的調(diào)用推遲到工作線程中。worker線程是非守護(hù)程序,以確保所有(緩慢的)阻塞I / O在解釋器退出之前完成,并保持對(duì)客戶端的弱引用(方法調(diào)用入隊(duì))。當(dāng)客戶端進(jìn)行垃圾回收時(shí),弱引用的回調(diào)將觸發(fā),并且工作線程知道不再有更多的工作排隊(duì),因此將在下一個(gè)方便時(shí)退出。在一個(gè)重要的用例中,這似乎可以正常工作:在日志記錄通道位于主線程中時(shí)。當(dāng)主線程停止/退出時(shí),日志記錄通道尚未完成,因此,我的(非守護(hù)程序)工作線程始終保持整個(gè)進(jìn)程運(yùn)行。
查看完整描述

1 回答

?
慕妹3242003

TA貢獻(xiàn)1824條經(jīng)驗(yàn) 獲得超6個(gè)贊

對(duì)于您的主線程而言,如果不調(diào)用join所有非守護(hù)程序線程而結(jié)束,或者對(duì)不執(zhí)行該操作會(huì)做出任何假設(shè),則是一個(gè)不好的主意。


如果你沒有做任何事情非常不尋常的,CPython的(至少2.0 - 3.3)將自動(dòng)調(diào)用覆蓋你join所有的非守護(hù)線程作為對(duì)_MainThread._exitfunc。實(shí)際上并沒有文檔記錄,因此您不應(yīng)該依賴它,但這就是您正在發(fā)生的事情。

您的主線程實(shí)際上根本沒有退出;它在_MainThread._exitfunc嘗試使用join任意非守護(hù)進(jìn)程線程時(shí)阻塞了內(nèi)部。它的對(duì)象在atexit調(diào)用處理程序之前不會(huì)最終確定,直到完成所有非守護(hù)程序線程的連接之后才會(huì)發(fā)生。


同時(shí),如果您避免這種情況(例如,直接使用thread/_thread或通過將主線程從其對(duì)象中分離或強(qiáng)制其進(jìn)入普通Thread實(shí)例),會(huì)發(fā)生什么情況?沒有定義。該threading模塊根本沒有引用它,但是在CPython 2.0-3.3中,并且可能在任何其他合理的實(shí)現(xiàn)中,它都由thread/_thread模塊來決定。而且,正如文檔所說:

當(dāng)主線程退出時(shí),系統(tǒng)定義其他線程是否存活。在使用本機(jī)線程實(shí)現(xiàn)的SGI IRIX上,它們可以生存。在大多數(shù)其他系統(tǒng)上,它們是在不執(zhí)行try ... finally子句或執(zhí)行對(duì)象析構(gòu)函數(shù)的情況下被殺死的。

因此,如果設(shè)法避免使用join所有非守護(hù)程序線程,則必須編寫代碼來處理它們,使其像守護(hù)程序線程一樣被硬殺死,并使它們繼續(xù)運(yùn)行直到退出。

如果它們確實(shí)繼續(xù)運(yùn)行(至少在POSIX系統(tǒng)上的CPython 2.7和3.3中),則可能仍保留主線程的OS級(jí)線程句柄以及代表該線程的各種更高級(jí)別的Python對(duì)象,并且它們不會(huì)被GC清除。 。


最重要的是,即使所有內(nèi)容都已發(fā)布,您也不能依靠GC刪除任何內(nèi)容。如果您的代碼依賴于確定性GC,在很多情況下,您都可以在CPython中使用它(盡管您的代碼隨后將在PyPy,Jython,IronPython等中中斷),但是在退出時(shí)并不是其中之一。CPython可以而且會(huì)在退出時(shí)泄漏對(duì)象,并讓OS對(duì)其進(jìn)行整理。(這就是為什么您永遠(yuǎn)不會(huì)關(guān)閉的可寫文件可能會(huì)丟失最后的幾次寫操作-該__del__方法永遠(yuǎn)不會(huì)被調(diào)用,因此沒有人告訴他們flush,并且至少在POSIX上,底層FILE*也不會(huì)自動(dòng)刷新。)

如果您希望在主線程完成時(shí)清理某些內(nèi)容,則必須使用某種close函數(shù)而不是依靠__del__,并且必須確保通過with圍繞主代碼塊,atexit函數(shù)或其他機(jī)制。


最后一件事:

我本來希望將線程局部變量釋放(即收集垃圾)...

您實(shí)際上在某處有線程局部變量嗎?或者,您是說僅在一個(gè)線程中訪問的局部變量和/或全局變量?


查看完整回答
反對(duì) 回復(fù) 2021-03-30
  • 1 回答
  • 0 關(guān)注
  • 224 瀏覽
慕課專欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)