簡體   English   中英

用不同的線程填充 std::vector

[英]Filling std::vector by different threads

我需要在不同的線程上填充一個 std::vector。

它是正確的代碼嗎? 或者我應該為我的代碼添加互斥鎖?

void func(int i, std::vector<float>& vec)
{
    vec[i] = i;
}

int main()
{
    std::vector<float> vec(6);
    std::list<std::thread> threads;
    for (int i = 0; i < 6; i++)
    {
        threads.push_back(std::thread(func, i, std::ref(vec)));
    }
    for (auto iter = threads.begin(); iter != threads.end(); iter++)
    {
      (*iter).join();
    }
}

我測試了我的代碼,它工作正常。 有什么陷阱嗎? 它是線程安全的代碼嗎?

如何通過不同的線程獲取 std::vector 數據?

相關問題:
std::vector 默認是線程安全和並發的嗎? 為什么或者為什么不? .

它是線程安全的,因為您沒有修改向量大小,也沒有嘗試在不同線程中寫入相同的 memory 位置。

為了將來為不深入鏈接的任何人證明此答案:

  1. 它不是線程安全的,只是因為它們使用了[]運算符。 它是線程安全的,因為每個線程都在顯式修改 memory 中的不同位置。

  2. 如果所有線程只使用[]讀取相同的位置,那將是線程安全的。

  3. 如果所有線程都寫入同一個位置,使用[]不會阻止它們相互干擾。

  4. 我認為,如果這是生產代碼,那么至少需要一條說明為什么這是線程安全的注釋。 如果有人修改此 function,則不確定是否有任何編譯時方法可以防止有人在腳上開槍。


在第 4 點,我們希望與此代碼的未來用戶溝通:

  1. 不,我們沒有保護這個標准庫容器,即使這應該是你的直覺反應,並且
  2. 是的,我們已經分析過了,它是安全的。

最簡單的方法是在那里發表評論,但有一種說法:

編譯器不會讀取注釋,我也不會。
-Bjarne Stroustrup

我認為某種[[attributes]]應該是這樣做的方法嗎? 盡管內置插件似乎不支持任何類型的線程安全檢查。


Clang 似乎提供了線程安全分析

該分析仍在積極開發中,但它已經足夠成熟,可以部署在工業環境中。

假設您實現了其他需要std::mutex負責您的std::vector的功能:

std::mutex _mu;
std::vector<int> _vec GUARDED_BY(_mu);

然后您可以顯式添加NO_THREAD_SAFETY_ANALYSIS屬性以關閉針對這一特定 function 的安全檢查。 我認為最好將其與評論結合起來:

// I know this doesn't look safe but it is as long as
// the caller always launches it with different values of `i`
void foo(int i, std::vector<int>& vec) NO_THREAD_SAFETY_ANALYSIS;

GUARDED_BY的使用告訴我,將來您正在考慮線程安全。 使用NO_THREAD_SAFETY_ANALYSIS表明您已確定此 function 可以使用 - 特別是當修改您的vector的其他函數未標記為NO_THREAD_SAFETY_ANALYSIS

是的,它是線程安全的,因為您既沒有從不同的線程寫入向量 object 本身,也沒有寫入向量底層數組中的同一個 object。

當您構造向量時,您為 6 個元素分配空間,並為int等 pod 類型填充零。 這些元素被放置在一個由向量擁有和管理的數組中,並且向量通過迭代器和operator []公開它們。

因此,當您編輯向量中的元素時,您不會編輯向量本身,因此您不必使用互斥鎖來保護向量。

如果要修改向量本身或不同線程中的相同元素,則需要互斥鎖。

暫無
暫無

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

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