2012-02-05 15 views
1

私は、Linux上のC/C++(いくつかの古いコードを含む)のスレッディングを通して、何百万ものフォルダを個別にコピーする作業を与えられています。スレッド同期の問題

フォルダのスキャン、ソースからコピー先フォルダへのファイルのコピーなど、個々の機能が適切に実行され、シリアルで実行すると適切に機能します。スレッド化によって完了したら、問題はすべて発生します。

問題:コードは実行するたびに少し違った動作をします。ときどきproeprlyフォルダのリスト全体をコピーしますが、失敗することもあります。

サンプル失敗が出力される。機能スレッドで

foldername is [Junk] tCount is 2 cntr is 3 

val of folder is Junk tid is 3055356816 

foldername is [Notes] tCount is 3 cntr is 4 

val of folder is tid is 3042966416 

Folder creation failed /var/anshul/work/copyDirectoryThreaded/test_copied/email/ 

渡された引数の値がNULLなります。上記の場合、引数Notesはmain関数からスレッド関数に渡されますが、スレッド関数では受け取った値はNULLです。

私の主なコードは次のようになります。

int main() 
{ 
    int cntr=0; 
    int Val = 3; 

    tCount = 0; 
    pthread_t thread[folderCount]; // folderCount is total number of folders scanned 
    int iret[folderCount]; 
    std::map<std::string,int>::iterator mFolderIt; // mFolder map contains the folder list. 
    char foldername[30] = {0}; 

    for (mFolderIt=mFolder.begin() ; mFolderIt != mFolder.end();) 
    { 
     if(tCount < Val) 
     { 
      pthread_mutex_lock(&mutex_tCount); 
      tCount++; 
      pthread_mutex_unlock(&mutex_tCount); 

      sprintf(foldername,"%s",(*mFolderIt).first.c_str()); 
      fprintf(stderr, "foldername is [%s] tCount is %d cntr is %d\n",foldername,tCount,cntr); 
      iret[cntr] = pthread_create(&thread[cntr], NULL,folderCopy , (void*)foldername); 
      cntr++; 
      usleep(1); // most crucial for threading....... 
      mFolderIt++; 
      memset(foldername,0,30); 
     } 
     else 
     { 
      while(tCount >= Val) 
      { 
       usleep(10); 
      } 
     } 
    } 

    for(int x = 0 ; x<folderCount ;x++) 
     pthread_join(thread[x],NULL); 

    return 1; 
} 

スレッド機能コード:

void * folderCopy(void *f) 
{ 
    fprintf(stderr,"val of folder is %s tid is %u\n", folder, (unsigned int)pthread_self()); 

    pthread_mutex_lock(&mutex_tCount); 
    tCount--; 
    pthread_mutex_unlock(&mutex_tCount); 
    pthread_exit(NULL); 
    return NULL; 
} 

誰かがこの問題を解決するために私を助けてください。

+0

スレッドプールパターンを使用して問題を解決することをお勧めします。とにかく、あなたのコードでは、wait-loopではなく、スレッドを同期させるためにstd :: condition_variableを使用するほうがよいでしょう。 –

+1

'usleep(1); //スレッドのために最も重要なことです....... 'は私に言う明るい赤い旗です:"私は壊れています! " pthread_createに渡すための 'foldername'のコピーを作り、それを使ってスレッドを解放してください。 – JimR

+0

heeheジム、まさに... !!!それを大声で叫ぶのが良い... :-) –

答えて

3
    fprintf(stderr, "foldername is [%s] tCount is %d cntr is %d\n",foldername,tCount,cntr); 
        iret[cntr] = pthread_create(&thread[cntr], NULL,folderCopy , (void*)foldername); 
        cntr++; 
        usleep(1); // most crucial for threading....... 
        mFolderIt++; 
        memset(foldername,0,30); 

usleepは十分な時間であるという保証はありません。代わりに、を確実ににして、他のスレッドが使用するまでメモリが有効であるようにする必要があります。これを実行する最も簡単な方法は、他のスレッドにデータの独自のコピーを与えることです:

iret[cntr] = pthread_create(&thread[cntr], NULL, folderCopy, strdup(foldername)); 
// ... 

void * folderCopy(void *f) 
{ 
    char *folderName = (char *)f; 
    // do something with folderName 
    free(f); 
    return NULL; 
} 

スレッドがデータのコピーを取ったことを確認する方法は他にもありますが、これは取得する最も簡単です右。

+0

ありがとうbdonlan .. that worked .. :-) –

1

4番目のパラメータとして渡されたポインタは、スレッドセーフではありません。

pthread_create(&thread[cntr], NULL,folderCopy , (void*)foldername); 

だから、すべてのスレッドが同じポインタを受信して​​いると、特定のスレッドが見てどのようなコンテンツを知る方法がないので、メインスレッドは、このポインタの内容をoverwrittingされているので。

スレッドごとにコンテンツのプライベートコピーを作成する必要があります(スレッドはそれをクリーンアップします)。