信号量问题

时间:2017-11-04 03:38:28

标签: c++ semaphore

我正在尝试理解信号量,并且无法通过给定的约束来解决我的实现问题。我使用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 ;
}

此线程应向母函数发送信号,该函数生成子线程并等待它们完成。

我的问题是,当我编译并运行时,有时不是所有的线程都显示为已完成,并且似乎与给定的约束不相同。

1 个答案:

答案 0 :(得分:1)

您还没有为我们发布足够的代码以便能够完全诊断错误(例如,您发布的内容中没有任何内容表明您确定线程是否已完成)。但是根据你发布的内容,似乎问题的至少一部分可能是线程5只等待来自0和2的信号然后信号“完成”而不管其他线程是否已经获得它们的信号,更不用说完成了他们的工作。

例如,线程0,2和5可以完成工作,而线程1,3或4根本不会运行。