2011-06-21 5 views
0

私は、POSIX共有メモリセグメントと名前のないセマフォを使用して整数の奇数偶数ソートを行うために基本的な並列処理を行っています。私は、セマフォーのロック/アンロックの直後にperror()をしないと、コードの動作が異なっています(そしてその後、正しくソートされません)。セマフォーのロックとロック解除の直後にperror()呼び出しをそのまま残すと、コードは整数の配列を完全にソートします。セマフォのロック/アンロックに影響するperror()呼び出しの問題

int semaphoreCheck = sem_init(&(sharedData->swapSem), 1, 1); 

if (semaphoreCheck == -1) 
{ 
    perror("failed to initialize semaphore"); 
    exit(EXIT_FAILURE); 
} 

pid_t fork1; 
fork1 = fork(); 
if (fork1 == 0) 
{ 
    // original.child 
    pid_t fork2; 
    fork2 = fork(); 
    if (fork2 == 0) 
    { 
     // child.child 
     // do a portion of the sort here 
     while(sharedData->evenSwap || sharedData->oddSwap) 
     { 
      // obtain lock on the shared vector 
      // int commandCheck = shmctl(sharedID, SHM_LOCK, NULL); 
      int commandCheck = sem_wait(&(sharedData->swapSem)); 
      perror("semaphore lock"); 
      // if lock was obtained 
      if (commandCheck == 0) 
      { 
       sharedData->evenSwap = false; 
       for(int index = 1; index < arraySize - 1; index +=2) 
       { 
        if(sharedData->vecData[index] > sharedData->vecData[index + 1]) 
        { 
         int temp; 
         temp = sharedData->vecData[index]; 
         sharedData->vecData[index] = sharedData->vecData[index+1]; 
         sharedData->vecData[index+1] = temp; 
         sharedData->evenSwap = true; 
        }  
       } 
       // release lock on the shared vector 
       commandCheck = sem_post(&(sharedData->swapSem)); 
       perror("semaphore unlock"); 
       if (commandCheck == -1) 
       { 
        perror("failed to unlock shared semaphore"); 
       } 
      } 
      else perror("failed to lock shared semaphore"); 
     } 
     _exit(0); 
    } 
    else if (fork2 > 0) 
    { 
     // child.parent 
     // do a portion of the sort here 
     while(sharedData->evenSwap || sharedData->oddSwap) 
     { 
      // obtain lock on the shared vector 
      int commandCheck = sem_wait(&(sharedData->swapSem)); 
      perror("semaphore lock"); 
      // if lock was obtained 
      if (commandCheck == 0) 
      { 
       sharedData->oddSwap = false; 
       for(int index = 0; index < arraySize - 1; index +=2) 
       { 
        if(sharedData->vecData[index] > sharedData->vecData[index + 1]) 
        { 
         int temp; 
         temp = sharedData->vecData[index]; 
         sharedData->vecData[index] = sharedData->vecData[index+1]; 
         sharedData->vecData[index+1] = temp; 
         sharedData->oddSwap = true; 
        }  
       } 
       // release lock on the shared vector 
       commandCheck = sem_post(&(sharedData->swapSem)); 
       perror("semaphore unlock"); 
       if (commandCheck == -1) 
       { 
        perror("failed to unlock shared semaphore"); 
       } 
      } 
      else perror("failed to lock shared semaphore"); 
     } 
     _exit(0); 
    } 
    else 
    { 
     // child.error 
     // forking error. 
     perror("failed to fork in child"); 
     exit(EXIT_FAILURE); 
    } 
} 
else if(fork1 > 0) 
{ 
    // original.parent 
    // wait for the child process to finish. 
    waitpid(fork1, NULL, 0); 

} 
else 
{ 
    // forking error 
    perror("failed to fork"); 
    exit(EXIT_FAILURE); 
} 

私はこれだけは待ち時間は満たすことができない場合はどのようにセマフォ・ブロックプロセスに関係していることを推測することができますが、私はにperror()呼び出しがそれを修正する方法を理解していません。

+2

マルチスレッドは奇妙なことがあります。もしバグがあると、正しい出力を得るためにスレッドのタイミングが変わる可能性があります。 C++を使用している場合、副次的な質問として、あなたの質問にブーストスレッディングライブラリでタグ付けされているものは、実際には単純化されています。私はそれを使用することをお勧めします。 – GWW

答えて

0

あなたの問題は、セマフォを取得した後も条件がまだ適用されているかどうかをチェックしているかどうか、またはチェック条件がそれ自体が間違っているかどうかに関係していると思います。

あなたはしている:あなたがセマフォを取得

while(sharedData->evenSwap || sharedData->oddSwap) 
    { 
     // obtain lock on the shared vector 
     int commandCheck = sem_wait(&(sharedData->swapSem)); 
     perror("semaphore lock"); 
     // if lock was obtained 
     if (commandCheck == 0) 
     { 
      sharedData->oddSwap = false; 

した後、あなたはおそらくsharedData->evenSwapまたはsharedData->oddSwapのいずれかがない場合はセマフォを放棄、まだ本当であることを検証する必要があります。これは標準的なイディオムです。元の小切手とロックを獲得した時点の間でステータスが変更された可能性があるため、チェック、ロック、再チェックを行います。

perror()コールは、プロセスのタイミングを変更し、条件がperror()コールが存在しない場合よりも長く変化しないようにします。ですから、どこかにタイミングの問題があります。

関連する問題