信号量的问题

Issues with Semaphores

本文关键字:问题 信号量      更新时间:2023-10-16

我正在尝试理解信号量,并且无法通过给定的约束来解决我的实现问题。我正在使用 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 << "nnBAD VALUE TO CASE STATMENT!!nn" ;
          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 << "nnBAD VALUE TO CASE STATMENT!!nn" ; 
          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 ... nn" ;
 pthread_mutex_unlock(&stdoutLock) ;
 return ;
 }

int main() 
{ 
cout << "nWelcome to The Child Thread Workplace!nn" ;
 /* This calls the function that performs initializations. */
init(); 
    /* Execute the mother() function */ 
mother();
return 0 ;
}

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

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

您尚未发布足够的代码,以便我们能够完全诊断出问题所在(例如,您发布的内容中没有任何内容表明您如何确定线程已完成或未完成)。 但是从您所做的帖子来看,似乎至少有一部分问题可能是线程 5 只等待来自 0 和 2 的信号,然后发出"完成"的信号,而不管其他线程是否已经获得了他们的信号,更不用说完成了他们的工作了。

例如,线程 0、2 和 5 可以在线程 1、3 或 4 完全不运行的情况下完成其工作。