簡體   English   中英

線程安全數組計數器 C++

[英]Thread-safe array counter C++

我有一個包含 1000 多個元素的向量。 我想獲取每個元素並使用該元素發出 HTTP 請求,然后在不使用多線程的情況下給我結果。 它會很慢,所以我做了多線程,每次都要檢查 100 個元素。

我的問題是,計數器不工作,因為我計划在不檢查所有元素的情況下使計數器達到最大值。

這是我的代碼片段:

for(int i=0; i<threads; i++){
    threadlist.push_back(thread([&]{
        while(true){
            mutex lock;
            lock.lock();
            if(counter >= Files::getUsers().size()){
                exit(0);
            }else {
                counter++;
            }
            lock.unlock();

您在線程內的循環內定義lock ,這意味着每個線程中的每次迭代都將擁有自己的互斥鎖,因此您不會獲得任何線程同步來保護counter 這會給您帶來數據競爭,這是未定義的行為。

您需要做的是在for循環之外定義lock ,就像您對counter所做的那樣,然后捕獲互斥量以便所有線程共享它。

或者,您可以將counter設為std::atomic<whatever_integer_type>然后您甚至不需要互斥鎖,因為counter會自行同步。

您似乎在每個線程中使用單獨的互斥鎖。 您需要在每個線程中使用相同的互斥鎖才能進行任何同步。

您不能為每個線程使用單獨的互斥鎖。 您可以在所有線程(或其他一些同步原語)中使用一個互斥量,或者在這種情況下可以使用原子值。

使用互斥鎖:

  std::vector<std::thread> threadlist;
  int counter = 0;
  std::mutex m;
  int num_threads = 8;
  for (int i = 0; i < num_threads; i++) {
      threadlist.push_back(thread([&]{
      while (true) {
        int myValue;
        {  // keep critical section minimal to avoid lock contention as much as possible
          std::lock_guard<std::mutex> lock(m);
          myValue = counter++;
        }
        if (myValue >= Files::getUsers().size()) {
          return;
        }
        //do calculation with myValue, no other thread will have the same
      }
     }));
  }

與原子

  std::vector<std::thread> threadlist;
  std::atomic<int> counter {0};
  int num_threads = 8;
  for (int i = 0; i < num_threads; i++) {
      threadlist.push_back(thread([&]{
      while (true) {
        int myValue = counter.fetch_add(1);
        if (myValue >= Files::getUsers().size()) {
          return;
        }
        //do calculation with myValue, no other thread will have the same
      }
     }));
  }

首先將要完成的工作划分為每個線程的單獨向量

首先為每個線程准備要完成的工作,這樣每個線程都會有自己獨立的工作負載:

   const int nThreads = NUMBER_OF_THREADS;
   const int sizePerThread = Files::getUsers().size() / nThreads;
   std::vector<std::thread> threadlist;

   // Fills index limits for each thread
   std::vector<int> threadLimitIndex;
   for (int i=0; i<nThreads; ++i)
     threadLimitIndex.push_back(i * sizePerThread);
   threadLimitIndex.push_back(Files::getUsers().size());

然后使用每個線程的限制讓它們在自己的數據集上工作:

   // Does the calculation
   for (int i=0; i<nThreads; ++i)
   {
     threadlist.push_back(thread([&threadLimitIndex]{
        for (int myValue=threadLimitIndex[i]; myValue<threadLimitIndex[i+1]; ++myValue)
        {
           // Do calculation with myValue, no other thread will have the same
        }
       }
     ));
   }

不需要復雜的控制代碼;-)

警告:這是一種分離工作的簡單方法,並假設每個值的工作大致相同 如果每個值要完成的工作差異很大,一些線程會提前完成並停止,而其余線程仍有工作要做,這不是最優的。 為了保證所有線程在所有情況下都工作到結束,你需要實現一個工作隊列

暫無
暫無

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

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