2017-11-04 3 views
0

私はセマフォを理解しようとしていますが、私の実装では制約を与えて問題を解決することはできません。私は制約付きで6つのスレッドを使用しています。 3は0と1を待たなければならない。 4は起動前に1と2を待たなければなりません。 5は0と2を待つ必要があります。私はこの特定の問題に対してswitch文を使用することに決めましたが、どこが間違っているのか分からないようです。セマフォに関する問題

#include <iostream> 
#include <sched.h> 
#include <time.h> 
#include <pthread.h> 
#include "sem.h" 
#include <cstdlib> 

#define THREAD_COUNT 6 

using namespace std; 

extern sim_semaphore create_sim_sem(int) ; 
extern void wait_sem (sim_semaphore) ; 
extern void signal_sem (sim_semaphore) ; 

pthread_mutex_t stdoutLock ; 


int thrds_finished ; 

// global sync variables 

sim_semaphore support_ready[THREAD_COUNT] ; 
sim_semaphore finished ; 



/* These are global variable to represent threads created 
    dynamically. */ 
pthread_t thr[THREAD_COUNT] ; 

/* This is included to facilitate adding random delays in the code 
    -- as a debugging aid. */ 
extern long random(void); 


int checking = 0 ; 

/* A data type - a struct (class) with an int field to represent 
    a thread ID. */ 
struct threadIdType 
{ 
int id ; 
}; 


void init() 
{ 

if (0!=pthread_mutex_init(&stdoutLock, NULL)) 
{ cout << "MUTEX INITIALIZATION FAILURE!" << endl ; 
exit(-1) ;} 

thrds_finished = 0 ; 

finished = create_sim_sem(0) ; 
int count ; 
for (count = 0; count < THREAD_COUNT ; count++) 
{ 
support_ready[count] = create_sim_sem(0) ; 
} 

    /* This initializes a random number generator */ 
srandom(time((time_t *) 0)); 
} 

void rand_delay(int max) 
{ 
int m_delay, j ; 
m_delay = (int) random()%max ; 
for (j=0; j<m_delay; j++) sched_yield(); 
} 

void childMessage (int ID) 
{ 
pthread_mutex_lock(&stdoutLock) ; 
cout << "Child # " << ID 
    << " has completed its assignment.\n" ; 
pthread_mutex_unlock(&stdoutLock) ; 
} 

void * child(void * idPtr) 
{ 

int me = ((threadIdType *) (idPtr))->id, temp ; 



rand_delay(100) ; 

    // wait constraints 
switch(me) 
{ 
    case 0: break ; // thread 0 just 'goes' 
    case 1: break ; // thread 1 just 'goes' 
    case 2: break ; // thread 2 just 'goes' 
    case 3: wait_sem (support_ready[0]) ; 
      wait_sem (support_ready[1]) ; // thread 3 waits for both 0 and 1 
      break ; 
    case 4: wait_sem (support_ready[1]) ; 
      wait_sem (support_ready[2]) ; // thread 4 waits for both 1 and 2 
      break ; 
    case 5: wait_sem (support_ready[0]) ; 
      wait_sem (support_ready[2]) ; // thread 5 waits for both 0 and 2 
      break ; 
    default: pthread_mutex_lock(&stdoutLock) ; 
      cout << "\n\nBAD VALUE TO CASE STATMENT!!\n\n" ; 
      pthread_mutex_unlock(&stdoutLock) ; 
      exit (-1); break ; 
    } 




    rand_delay(1000) ; 

     /* Next increment thrds_finished - to keep track 
     of how many child processes have finished their 
     tasks. */ 

     /* Here put code you may need for protecting 
     thrds_finished. */ 
    /* HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH */ 


    /* HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH */ 
     /* This code increments thrds_finished in a way 
      that magnifies the problem if the critical section 
      problem is not solved correctly. Of course, 
      do not change this part of the code. */ 
    temp = thrds_finished ; 
    rand_delay(1000) ; 
    temp++ ; 
    rand_delay(1000) ; 
    thrds_finished = temp ; 

     /* Here put additional code you may need for protecting 
     thrds_finished. */ 
    /* HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH */ 




    /* HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH */ 
     /* Announce completion of the assignment. */ 
    childMessage(me) ; 


    switch(me) 
    { 
    case 0: signal_sem(support_ready[0]); 
      signal_sem(support_ready[0]); // thread 0 signals for threads 3 5 
      break ; 
    case 1: signal_sem(support_ready[1]) ; // thread 1 signals for 3 4 
      signal_sem(support_ready[1]) ; 
     break ; 
    case 2: signal_sem(support_ready[2]) ; // thread 2 signals for 4 5 
      signal_sem(support_ready[2]) ; 
     break; 
    case 3: break; 
    case 4: break; 
    case 5: signal_sem (finished); break; // thread 5 signals to the mother 
    default: pthread_mutex_lock(&stdoutLock) ; 
      cout << "\n\nBAD VALUE TO CASE STATMENT!!\n\n" ; 
      pthread_mutex_unlock(&stdoutLock) ; 
      exit (-1); break ; 
    } 



    pthread_exit ((void *)0) ; 
    } 


    // spawn child threads and waits for them to finish 
    void mother() 
    { 
    int i; 


    threadIdType * idPtr ; 

    /* Create child threads numbered 1 through 8. */ 

    pthread_mutex_lock(&stdoutLock) ; 
    cout << "Mother Begins Spawning Threads.\n" << endl ; 
    pthread_mutex_unlock(&stdoutLock) ; 

    for (i = 0; i < THREAD_COUNT ; i++) 
    { 
    idPtr = new threadIdType ; /* allocate memory for struct */ 
    idPtr->id = i ; /* records current index as the child's ID */ 



    if (0!=pthread_create(&thr[i], NULL, child, (void *) idPtr)) 
    { pthread_mutex_lock(&stdoutLock) ; /* 'error out' code here */ 
    cout << "THREAD CREATION FAILURE!" << endl ; 
    pthread_mutex_unlock(&stdoutLock) ; 
    exit(-1) ; } 



    if (0!=pthread_detach(thr[i])) 
    { pthread_mutex_lock(&stdoutLock) ;/* 'error out' code here */ 
    cout << "THREAD DETACHMENT FAILURE!" << endl ; 
    pthread_mutex_unlock(&stdoutLock) ; 
    exit(-1) ;} 
    } 

    rand_delay(3000) ; /* Simulate whatever may delay the mother thread */ 

    pthread_mutex_lock(&stdoutLock) ; 
    cout << "Mother Finishes Spawning Threads.\n" << endl ; 
    pthread_mutex_unlock(&stdoutLock) ; 

    /* Some synchronization code is needed here to make the mother 
    behave correctly - she is not supposed to exit until after 
    all the children have finished their tasks. */ 

    wait_sem (finished) ; 


pthread_mutex_lock(&stdoutLock) ; 
cout << "\nAll children have now reported that they finished.\n" ; 
cout << "The value of the thrds_finished counter is: " ; 
cout << thrds_finished << ".\n" ; 
if (thrds_finished != THREAD_COUNT) 
cout << "BAD COUNTER VALUE!! - Critical Section Problem Failure!!\n" ; 
cout << "Mother exiting ... \n\n" ; 
pthread_mutex_unlock(&stdoutLock) ; 
return ; 
} 



int main() 
{ 

cout << "\nWelcome to The Child Thread Workplace!\n\n" ; 

/* This calls the function that performs initializations. */ 
init(); 

    /* Execute the mother() function */ 
mother(); 

return 0 ; 
} 

このスレッドは、子スレッドを生成するマザー関数にシグナルを送信し、それらが終了するのを待つ必要があります。

私の問題は、私がコンパイルして実行したときに、すべてのスレッドが完了しているとは限らず、与えられた制約から同期していないように見えることです。

+0

C++ 11を使用していますか?もしそうなら、私はそれに答えることができます – DeepakKg

+0

はい私はこれがC++を使用していると信じています11 – sippycup

答えて

1

私たちが何が間違っているかを完全に診断するための十分なコードを投稿していません(例えば、スレッドが完了したかどうかを判断する方法を示す投稿には何もありません)。しかし、あなたが投稿したことから、問題の少なくとも1つは、スレッド5が0と2の信号を待つだけで、他のスレッドが信号を受け取ったかどうかに関係なく、彼らの仕事を完了した。

例えば、スレッド0、スレッド2、スレッド5はスレッド1、スレッド3、スレッド4を実行しなくても作業を終了できます。

+0

私が働いているコードの塊を追加し、あなたが私に与えたその信号の提案を調べます – sippycup

+0

私の提案は、完了したときに 'signal_sem(finished)'を実行し、マザースレッドがそのセマフォを適切な回数待つようにします。それから、すべてのスレッドが完了したことがわかります。 –