2017-03-08 72 views
0

予實現的併發隊列與兩個方法:添加(排隊)& 除去(出列)。C++:傳遞線程ID的功能異常

要使用2個線程測試我的實現,我在一個名爲getRandom()的方法中生成了10個(NUMBER_OF_OPERATIONS)0到1之間的隨機數。這使我可以創建不同的增加和刪除操作分配。

doWork方法拆分了多個線程完成的工作。

問題:我從主函數傳入的threadID與doWork方法接收的threadID不匹配。下面是一些樣品運行:

Output 1

Output 2

#define NUMBER_OF_THREADS 2 
#define NUMBER_OF_OPERATIONS 10 

int main() { 

     BoundedQueue<int> bQ; 
     std::vector<double> temp = getRandom(); 
     double* randomNumbers = &temp[0]; 
     std::thread myThreads[NUMBER_OF_THREADS]; 

     for(int i = 0; i < NUMBER_OF_THREADS; i++) { 
      cout << "Thread " << i << " created.\n"; 
      myThreads[i] = std::thread ([&] { bQ.doWork(randomNumbers, i); }); 
     } 

     cout << "Main Thread\n"; 

     for(int i = 0; i < NUMBER_OF_THREADS; i++) { 
      if(myThreads[i].joinable()) myThreads[i].join(); 
     } 
     return 0; 
    } 

    template <class T> void BoundedQueue<T>::doWork (double randomNumbers[], int threadID) { 

     cout << "Thread ID is " << threadID << "\n"; 
     srand(time(NULL)); 
     int split = NUMBER_OF_OPERATIONS/NUMBER_OF_THREADS; 
     for (int i = threadID * split; i < (threadID * split) + split; i++) { 
      if(randomNumbers[i] <= 0.5) { 
       int numToAdd = rand() % 10 + 1; 
       add(numToAdd); 
      } 
      else { 
       int numRemoved = remove(); 
      } 
     } 
    } 

回答

3

在這一行你被引用捕捉i

myThreads[i] = std::thread ([&] { bQ.doWork(randomNumbers, i); }); 

這意味着,當其他線程運行lambda,它會得到我的最新值,而不是它創建時的值。通過值捕捉它,而不是:

myThreads[i] = std::thread ([&, i] { bQ.doWork(randomNumbers, i); }); 

請告訴我更糟,因爲你有無序讀寫i,當前的代碼未定義behavoir。事實上,在其他線程讀取之前,主線程可能已經超出了範圍。上面的修復修復了所有這些問題。

+1

值得一提的是,線程產生和線程執行線程函數之間存在延遲。線程構造函數在線程生成時儘快返回控制權,因此在線程函數運行之前,您可以實際更改很多變量。 –

+1

這是做到了。謝謝邁克! – John

+0

@Revolver_Ocelot我是多線程編程的新手。這是一個值得關注的問題嗎? – John