我正在尝试理解信号量,并且无法通过给定的约束来解决我的实现问题。我使用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 :(得分:1)
您还没有为我们发布足够的代码以便能够完全诊断错误(例如,您发布的内容中没有任何内容表明您确定线程是否已完成)。但是根据你发布的内容,似乎问题的至少一部分可能是线程5只等待来自0和2的信号然后信号“完成”而不管其他线程是否已经获得它们的信号,更不用说完成了他们的工作。
例如,线程0,2和5可以完成工作,而线程1,3或4根本不会运行。