信号量算法同步故障

时间:2017-11-04 21:40:48

标签: c++ multithreading algorithm semaphore

我试图理解如何使用信号量同步一些线程与给定的约束0,1,2完成工作; 3必须等待0和1; 4开始前必须等待1和2; 5应该等待0和2.我相信我的等待实现是正确的但是一旦我发送信号我得到丢失孩子的输出。我的问题是我的同步实现错误了吗? 期望是这样的:

Mother Begins Spawning Threads.

Mother Finishes Spawning Threads.

Child # 2 has completed its assignment.
Child # 0 has completed its assignment.
Child # 1 has completed its assignment.
Child # 5 has completed its assignment.
Child # 3 has completed its assignment.
Child # 4 has completed its assignment.

现在所有的孩子都报告他们已经完成了。

#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: signal_sem(support_ready[me]) ;break;
  case  4: signal_sem(support_ready[me]) ;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 个答案:

没有答案