當要捕獲信號的目標執行緒被阻塞時,信號及其占用的記憶體會發生什么變化?
信號是否進入佇列?
佇列是否溢位,我們會丟失一些信號?
如果沒有,我們是否會發生記憶體泄漏?
uj5u.com熱心網友回復:
一般來說,信號的產生速度可能比它們消耗的速度快。僅當您使用排隊連接時才會發生這種情況。這通常發生在多執行緒代碼中(默認使用排隊連接)或者如果您使用 flag 設定連接Qt::QueuedConnection。
如果您的連接未排隊,則不會發生這種情況,因為信號在發出后立即由插槽同步處理。所以未處理的信號不會在佇列中等待。
因此,當您有一個排隊的連接并且生成和發出信號的速度比消費事件回圈處理它們的速度快時,它們當然會被排隊,它們占用記憶體(堆),如果運行時間足夠長,記憶體最終可能會耗盡(你可能會觀察 RAM 交換到磁盤,減慢您的系統使其無法使用)。當您詢問記憶體泄漏時 - 這可能不會發生。但是記憶體泄漏是您最不關心的問題。
所以你必須避免這種產生信號過快的情況。有很多選擇如何做到這一點。例如,您可以在發射方中有一個計時器,如果最新信號在小于 100 毫秒之前發出,則該計時器不允許發射信號。(我在我的應用程式的進度條中使用它。)
另一種選擇是實作雙向通信,其中發射器將發送一個信號,接收器將對其進行處理,并將回傳另一個信號作為確認處理已完成的回應,并且該信號將由發射器接收原始信號,通知它現在可以安全地發出另一個信號。
另一種選擇是不使用信號和插槽并直接呼叫方法,但當然您需要使用原子或鎖定互斥鎖來建立適當的同步機制。請注意,在這種情況下,信號不會在佇列中等待,但執行緒可能會因為過于頻繁地相互阻塞而表現不佳。
所以這取決于你選擇哪種方法。但是,當您發出信號的速度比在與排隊連接連接的插槽中處理它們的速度更快時,您絕對必須避免這種情況。
uj5u.com熱心網友回復:
當發出信號并通過排隊連接連接到某些物件時,每個連接都會在堆上分配一個事件,并發布到與接收物件關聯的事件佇列。
一旦事件被處理,它就會被洗掉。雖然未處理該事件,但它會占用一些堆空間,因此如果您繼續將事件發布到佇列但它不會在另一端耗盡,那么您會繼續增加記憶體消耗而不會減少它。您可以將其視為記憶體泄漏。佇列的大小未指定,但很可能您不能溢位它而不會導致未定義的行為(或已定義的例外,例如std::bad_alloc)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/480669.html
