2012-03-14 25 views
11

如果我在主線程中創建了一個C++對象,然後啓動另一個線程,並從該線程調用我創建的對象的公共成員函數,會發生什麼情況?如果我從另一個線程調用一個對象成員函數會發生什麼?

它是不同的,如果公共函數的參數,或者如果它操縱私有對象成員?

是否行爲不同在Windows,Linux或Mac OS?

如果在棧上創建對象,會發生什麼?

回答

9

有兩點重要:

  • 第一,像往常一樣,你需要esnure該實例的生命週期超過其使用期限。其次,跨多個線程訪問變量需要同步以防止競爭條件。

這就是所有人。

+0

如果我在堆上創建了對象,當最後一個線程退出時,是否有任何簡單的方法來刪除對象? – neckTwi 2013-10-30 15:57:57

3

如果我在主線程中創建了一個C++對象,然後啓動另一個線程,並從該線程我把我創建的對象的公共成員函數,會發生什麼?

它取決於對象的生命週期。

如果在堆上創建對象(動態內存使用new),則另一個線程將正確訪問對象的成員(假設沒有競爭條件),除非通過在第一個線程中調用delete來終止對象的生命週期。

如果堆棧(本地)在第一個線程創建的對象,那麼你將有一個* 未定義行爲 *如果創建的對象的生命週期中的第二個線程被訪問之前結束。

爲什麼你可以在第二個線程訪問堆棧上的對象?

每個線程都有自己的堆棧,除非在線程的堆棧中創建的對象是有效的和活着你會試圖訪問不指向第二個線程任何有效的對象的地址位置。
注意,每個過程有一個地址空間,並在同一進程共享所有線程相同的地址空間,因此該變量的地址可以在所述第二線程訪問。但是,您需要確保該地址包含有效的對象。

如果公共函數有參數或者它操作私有對象成員,它有什麼不同?

訪問說明和多線程都沒有關係。
相同的訪問說明符規則適用於所有線程。

是否行爲不同在Windows,Linux或Mac OS?

對所有操作系統都保證了#1的答案。

+5

對不起,這是不正確的。如果物體的壽命大於線程的壽命,那麼就可以。但要小心比賽條件。 – knivil 2012-03-14 08:03:47

+0

@knivil:對。我意識到我錯過了這個說法。編輯。 – 2012-03-14 08:10:39

4
  1. 每個線程都有自己的堆棧,因此您可以有併發的執行流。讓對象線程安全是你自己的責任。

  2. 沒關係。但是,私人成員是競爭條件的候選人。

  3. 如果您在堆棧上創建對象,將無法從其他線程訪問該對象。

+8

「如果您在堆棧上創建一個對象,將無法從其他線程訪問該對象。」除非您將該對象的引用傳遞給另一個線程。 – 2012-03-14 08:04:04

+0

@NicolBolas:是的,你說得對,當然。我應該更好地說「可見」。 – Matthias 2012-03-14 08:51:13

2

與原始行爲相比,如果在堆上創建,應該沒有區別。但是,當然有一些罪魁禍首,通常在「線程安全」這個術語下是已知的。如果你從不同的線程訪問同一個成員,你必須保證訪問相同的資源不會導致「競爭條件」。

爲避免競爭條件,您可以使用不同類型的「鎖」,例如互斥鎖等。使用鎖對象時,還有另一個元兇:如果兩個訪問器互相等待,鎖永遠不會被釋放。

2

它會工作得很好。對象不屬於任何特定的線程,同樣可以從任何地方調用。

但是,這很重要,同時在兩個線程上調用成員函數會導致您在一個線程中更新某些數據的同時在另一個線程中讀取數據時出現問題。您需要安排代碼以確保不會發生這種情況,或確保您的線程協調訪問(最有可能使用互斥鎖)

2

如果您從同一個 線程調用它,會發生什麼情況。相同的機器碼被執行。唯一潛在的 不同之處在於,您可以有多個線程同時訪問 處的對象;這是由你來防範(至少如果任何 的線程修改對象—否則,沒有保護是 需要)。

對於堆棧中的對象,您必須考慮生命期問題 ,但無論如何都是如此;在全局變量中保存一個指向 堆棧上的對象的指針,然後保留定義對象爲 的範圍,並且全局變量變爲懸掛指針;試圖通過它訪問對象 是未定義的行爲(並且調用一個非靜態成員函數 它被認爲使用它)。無論是 的訪問是來自同一個線程還是不同的線程都不會改變 的任何內容。

相關問題