[英]Thread-safety with C++11 and passing by reference with temporary object
[英]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
)。
您的問題在聲明sA
和sB
位置有點模糊。 聽起來它們是在一個函數內聲明的,在這種情況下你是正確的,每個線程都有它自己的sA
和sB
版本。 但是,如果它們在全球范圍內宣布的奇怪機會,情況並非如此。 如果我正確地理解了你的問題,你的意思是兩者都是在本地范圍內宣布的,所以你的第一點是正確的。 出於同樣的原因,你的第二點也是正確的。
不過,你的第三點很棘手。 在您的特定情況下,沒有共享內存,因此您的程序是一個“線程安全”程序(不確定這是否是一個很好的方式來說它)。 但是,函數AreStringsEqual
不是線程安全的。 在未來的某個時刻,您(或他人)可以使用與共享數據的功能,和功能本身並不能守住自己免受這種用法。
除非QString
指定operator==
是線程安全的,否則該函數不是線程安全的。 AreStringsEqual
的實現本身不會保護數據。
您正在使用此實現將線程安全的責任放在客戶端上。 在AreStringsEqual
,客戶端必須確保參數和參數的內部數據不會發生變異(例如,通過另一個線程)。 因此,他們可能會發現自己不必要的副本。 這究竟是如何發生的,取決於QString
的實現。 甚至std::string
實現也有很大差異=)
對於並發上下文中的字符串,通常會在將字符串移動到並發上下文之前獲取副本。 如果真的需要共享,你需要一些東西來保護它(比如鎖)。 對於原始集合(例如std::string
和std::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.