簡體   English   中英

使用C ++進行線程安全並通過引用傳遞

[英]Thread-safety with C++ and passing by reference

我想確認我對線程的理解並通過C ++中的引用傳遞。 以下功能線程是否安全?

QString sA = "hello";
QString sB = "world";
bool someFlag = AreStringsEqual(sA,sB);

...

bool AreStringsEqual(QString const &stringA, QString const &stringB)
{
    if(stringA == stringB)
    {   return true;   }

    return false;
}

我認為它線程安全的。 如果有人能確認我的思考過程,或者告訴我我不知道我在說什么,我會喜歡它:)

  • 進程內存中有兩個sA和sB副本。 在Thread1的堆棧上創建一個集合,在Thread2的堆棧上創建第二個集合。 因為我們通過引用傳遞,所以每個線程在內存中只需要一組sA和sB來執行函數調用。

  • 如果我們通過值傳遞,則在進程的內存中最多可以有四個sA和sB副本(每個線程有兩個集合),在某個時間點,兩個線程都在函數調用中交換處理器控制。

  • 在任何情況下都不共享內存,因此該函數是線程安全的。

對不起,如果這個問題非常簡單,那么線程已經讓我的大腦變得干脆

PRIS

沒有理由說兩個線程不能保存對相同字符串的引用。

此函數不是線程安全的,因為語句if(stringA == stringB)不是原子的。 首先從內存中獲取stringA ,然后才獲取string B

讓我們保持stringA == stringB == 2

你獲取stringA ,然后有一個上下文切換,stringA和stringB都變為3.然后你獲取stringB 雖然stringA一直等於stringB但你的函數會返回false(因為2 != 3 )。

您的問題在聲明sAsB位置有點模糊。 聽起來它們是在一個函數內聲明的,在這種情況下你是正確的,每個線程都有它自己的sAsB版本。 但是,如果它們在全球范圍內宣布的奇怪機會,情況並非如此。 如果我正確地理解了你的問題,你的意思是兩者都是在本地范圍內宣布的,所以你的第一點是正確的。 出於同樣的原因,你的第二點也是正確的。

不過,你的第三點很棘手。 在您的特定情況下,沒有共享內存,因此您的程序是一個“線程安全”程序(不確定這是否是一個很好的方式來說它)。 但是,函數AreStringsEqual 不是線程安全的。 在未來的某個時刻,您(或他人)可以使用與共享數據的功能,和功能本身並不能守住自己免受這種用法。

除非QString指定operator== 線程安全的,否則該函數不是線程安全的。 AreStringsEqual的實現本身不會保護數據。

您正在使用此實現將線程安全的責任放在客戶端上。 AreStringsEqual ,客戶端必須確保參數和參數的內部數據不會發生變異(例如,通過另一個線程)。 因此,他們可能會發現自己不必要的副本。 這究竟是如何發生的,取決於QString的實現。 甚至std::string實現也有很大差異=)

對於並發上下文中的字符串,通常會在將字符串移動到並發上下文之前獲取副本。 如果真的需要共享,你需要一些東西來保護它(比如鎖)。 對於原始集合(例如std::stringstd::vector ),您將希望避免在每次訪問時鎖定,因為它會破壞性能並且可能很容易失敗。 因此,如果必須共享非顯式線程安全的對象,通常會復制或鎖定。

因此, AreStringsEqual的實現不是線程安全的(除非bool QString::operator==(const QString&) const保證是線程安全的)。

但是,您對AreStringsEqual使用

QString sA = "hello";
QString sB = "world";
bool someFlag = AreStringsEqual(sA,sB);

對於大多數字符串實現來說都沒問題,因為參數及其數據對於線程是本地的。

如果線程之間共享sA和sB,則該函數不是線程安全的。

很可能在一個線程中執行函數AreStringsEqual期間,另一個線程嘗試修改sA或sB或兩者的值,然后會出現Race條件。

雖然您的函數沒有修改值,但函數外部的代碼可以。

因此最好使用pass by value,因為該函數將在堆棧上具有本地副本,這保證是線程安全的

首先,如果它們總是具有相同的值,那么為什么你需要相同字符串的兩個副本並不清楚。

也許它是基於你描述的上下文的線程安全,但只是看它自己的函數,它不是線程安全,因為在執行if條件時,字符串的值可能已經改變。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM