2017-11-04 76 views
0

我想了解信号量并且无法用给出的约束条件来解决问题。我正在使用6个线程的约束:0,1,2尽快完成工作; 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

您还没有发布足够的代码,能够完全诊断出什么问题(例如,您发布的内容中没有任何内容表示您确定线程是否已完成)。但是根据你发布的信息,似乎至少有一部分问题可能是线程5仅等待0和2的信号,然后信号“完成”,而不管其他线程是否获得了它们的信号,更少完成他们的工作。

例如,线程0,2和5可以完成他们的工作,而不需要线程1,3或4运行。

+0

我添加了我正在使用的代码块,并将查看您给我的信号建议 – sippycup

+0

我的建议是让每个子线程调用'signal_sem(finished)'完成后,让母线在该信号量上等待适当的次数。然后它会知道所有线程都已完成。 –