2016-10-23 5 views
0

私はマルチスレッドのプログラムを書いたことがありますが、それは正常に終了するとは思われません。ほとんどの場合、実行されてエラーを出さないようですが(戻り値で終了しない)、すべてのループを出力できず、実行時エラーが発生します。私はマルチスレッドにはまだまだ従っていますが、多かれ少なかれ続きますthis guideマルチスレッドプログラムが正しく終了しないのはなぜですか?

私はここで何が欠けていますか?スレッドを終了させるのは何らかの罠だと思いますが、pthread_exitで覆われていることが分かります。私に何か目立つものがあるかどうかを見て、私に知らせてください。ありがとう!

#include <iostream> 
#include <time.h> 
#include <vector> 
#include <fstream> 
#include <sstream> 
#include <cstdlib> 
#include <pthread.h> 
#include <string> 

using namespace std; 

struct threadData { 
    int  thread_id; 
    int* tArray; 
    int  tArraySize; 
    int  tQuery; 
}; 

//this is included because for whatever reason the std::to_string fxn is not recognized by my compiler 
template <typename T> 
std::string to_string(T value) 
{ 
     //create an output string stream 
     std::ostringstream os ; 

     //throw the value into the string stream 
     os << value ; 

     //convert the string stream into a string and return 
     return os.str() ; 
} 

//Counts the number of times the query is in the array 
int countInstance(int* array, int arraySize, int query) 
{ 
    int numInstance = 0; 

    for (int i = 0; i < arraySize; i++) 
    { 
     if (array[i] == query) 
      numInstance += 1; 
    } 

    return numInstance; 
} 

void *threadFunction(void *threadArg) 
{ 
    struct threadData *thisThread; 

    thisThread = (struct threadData *) threadArg; 

    //Originally wanted to use this to print each string, but it seemed to have issues printing correctly due to simultaneous threads 
    /*cout << "Query: "   << thisThread->tQuery 
     << "\tCount: " << countInstance(thisThread->tArray, thisThread->tArraySize, thisThread->tQuery) 
     << "\tThreadID: " << thisThread->thread_id << endl;*/ 

    //Decided to create a concatenated string of the desired phrase instead. 
    string queryString = to_string(thisThread->tQuery); 
    string instanceString = to_string(countInstance(thisThread->tArray, thisThread->tArraySize, thisThread->tQuery)); 
    string idString = to_string(thisThread->thread_id); 
    string outputString = "Query: " + queryString + "\tCount: " + instanceString + "\tThreadID: " + idString + "\n"; 

    cout << outputString; 

    pthread_exit(NULL); 
} 

int main(void) 
{ 
    int arraySize = 1000; 
    int numArray[arraySize]; 

    srand(time(NULL)); 

    //Populate array with random values ranged [0, 100] 
    for (int i = 0; i < arraySize; i++) 
    { 
     numArray[i] = (rand() % 101); 
    } 

    vector<int> numList; 

    numList.push_back(1); 
    numList.push_back(3); 
    numList.push_back(5); 
    numList.push_back(7); 

    pthread_t threads[numList.size()]; 
    struct threadData data[numList.size()]; 
    int rc; 

    for (int i = 0; i < numList.size(); i++) 
     { 
      data[i].tArray = numArray; 
      data[i].tArraySize = arraySize; 
      data[i].thread_id = i; 
      data[i].tQuery = numList[i]; 
      rc = pthread_create(&threads[i], NULL, threadFunction, (void *)&data[i]); 
      if (rc) 
       exit(-1); 
     } 
    pthread_exit(NULL); 
    return 0; 
} 
+0

threadFunction()に渡す* threadArg *ポインタが迷惑メールです。これは、スレッドが実行されるまでには*もはや実行されていないかもしれない関数のローカル変数です。より永続的な場所を探してデータを保存します。一般的な火災と忘れスレッドのバグbtw。 –

+0

@HansPassant、ここで推奨される解決策は何ですか?私はその構造体にデータを格納してはいけませんか? – Brendan

答えて

1

代わりのpthread_exit(NULL)を呼び出しますが完了するまでに、スレッドを待つjoin呼び出しのループを置く必要があります。

for (int i=0; i<numlist.size(); i++) { 
    void *rv; 
    pthread_join(threads[i], &rv); 
} 

pthread_exitはそれを中止するメインスレッドと異なるスレッドで使用されていますその自然終了の前に。

+0

ありがとう!これは完全に機能しました。実践的な違いが、元のループとそれを実行している中でこれを実行していることが分かりますか?私はスタンドアローンのループとして実行したときにスレッドが大部分は終了したが、必ずしもそうではないことに気づいた。しかし、これを既存のループの最後に挿入すると、作成された順序でスレッドが印刷されるようです。 – Brendan

+0

'join'操作は、「スレッドが終了するのを待つ」ことを意味します。ループの中に 'join'を置くと、プログラムは本当にマルチスレッドではありません(メインスレッドは新しいスレッドを生成しますが、直ちに終了して次のスレッドを開始するのを待つことになります)。最初にすべてのスレッドを開始してから、すべてのスレッドを待ってから後で並列に実行します。並列処理を見るには、ジョブの長さを十分に長くし、速度の向上を目指す必要があります。マルチスレッドハードウェアも必要です。単一のコアCPUではマルチスレッドアルゴリズムが長くかかるだけです。 – 6502

+0

説明に感謝します。 – Brendan

関連する問題