我被分配了一个程序来正确使用wait()
和signal()
函数作为信号量。任务是“隐喻地”创造钻石形成。
在纸面上,它将以分层方式看起来像这样
08 06 07 03 04 05 01 02 00 Thread #08 cannot join the diamond until threads #06 and #07 are both in position. Thread #07 cannot join until threads #04 and #05 are both in position. Thread #06 cannot join until threads #03 and #04 are both in position. and so on...
到目前为止,这是我的工作
DIAMOND.CPP
/* Diamond Formation Program */
#include <iostream>
#include <sched.h>
#include <time.h>
#include <pthread.h>
#include "sem.h"
#define THREAD_COUNT 9
using namespace std;
extern sim_semaphore create_sim_sem(int) ;
extern void wait_sem (sim_semaphore) ;
extern void signal_sem (sim_semaphore) ;
/* For technical reasons, we use the pthread mutex below,
instead of a semaphore, to lock the screen for output. Don't
change this. */
pthread_mutex_t stdoutLock ;
/* Here (between the lines) declare whatever shared
variables you need for
synchronization - such as semaphores, flags, counters,
and so forth. Variables declared here will be visible
to (shared by) all the threads in the task. */
/* HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH */
sim_semaphore tCount[THREAD_COUNT] ;
//declare array semaphore
/* HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH */
/* 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);
/* This can be changed to 1, but the resulting diagnostic output
will probably seem excessive. */
int checking = 0 ;
/* A data type - a struct (class) with an int field to represent
a thread ID. */
struct threadIdType
{
int id ;
};
/* ################################################## */
/* init */
/* ################################################## */
void init()
{
int index ;
/* This code initializes special mutex lock for screen output.
Just leave this alone. */
if ( 0!=pthread_mutex_init(&stdoutLock, NULL) )
{ cout << "MUTEX INITIALIZATION FAILURE!" << endl ;
exit(-1) ;}
/* Between the lines below, insert the code you want to
initialize the shared variables you are using for
synchronization - like semaphores, flags,
counters, and so forth. */
/* HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH */
for (index=0; index<THREAD_COUNT; index++) tCount[index] = create_sim_sem(1) ;
//best use a for-loop for this to initialize
/* HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH */
/* This initializes a random number generator */
srandom(time((time_t *) 0));
}
/* ################################################## */
/* rand_delay */
/* ################################################## */
void rand_delay(int max)
{
int m_delay, j ;
m_delay = (int) random()%max ;
for (j=0; j<m_delay; j++) sched_yield();
}
/* ################################################## */
/* childMessage */
/* ################################################## */
void childMessage (int ID)
{
pthread_mutex_lock(&stdoutLock) ;
cout << "Child # " << ID
<< " is now in position.\n" ;
pthread_mutex_unlock(&stdoutLock) ;
}
/* ################################################## */
/* child */
/* ################################################## */
void * child(void * idPtr)
{
/* This is just a change of data type for convenience. Now
'me' is the number of the child. Children have numbers from
0 to 8. */
int me = ((threadIdType *) (idPtr))->id, temp ;
/* Delay code inserted here to magnify the chances that child
threads will delay each other. The student
completing the program should think of more ways to insert
random delays that are likely to 'stress test' the program. */
rand_delay(100) ;
/* You need to put some of the synchronization code
between the lines, before the statement further down,
where the child process declares it has
put itself into position. */
/* HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH */
wait_sem (tCount[me*2+1]) ;
wait_sem (tCount[me*2+2]) ;
/* HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH */
childMessage(me) ; // get into position
/* Depending on what amount of synchronization code you placed
earlier in this function, you may need some more between
these lines, before the child exits (and 'dies'). */
/* HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH */
if (me==0) {
signal_sem (tCount[0]);
}
//signal when done
/* HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH */
pthread_exit ((void *)0) ;
}
/* ################################################## */
/* mother */
/* ################################################## */
/* The mother spawns child threads and then waits for
them all to finish. The mother's waiting has to be
implemented as part of the overall protocol - using
the sim_semaphore data type. */
void mother()
{
int i;
/* This is a pointer to a struct (class) that contains an int
field - it is a convenient data type to use as the parameter
to the child function. */
threadIdType * idPtr ;
/* Create child threads numbered 1 through 8. The mother
will play the role of position #9 */
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 */
/* The call below is what actually creates the child thread
and passes a pointer to the struct 'idPtr' as the
parameter to the child function. */
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) ; }
/* The call to pthread_detach() below marks a child
thread as 'detached' so that the system will not
expect the parent to 'join' (wait for) it. */
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) ;}
}
pthread_mutex_lock(&stdoutLock) ;
cout << "Mother Finishes Spawning Threads.\n" << endl ;
pthread_mutex_unlock(&stdoutLock) ;
/* Some protocol code is needed here to make the mother behave
correctly - she is not supposed to return to main and
exit until all the children have taken their positions. */
/* HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH */
for (i=1; i<THREAD_COUNT; i++) //mother checks
wait_sem (tCount[i]) ;
//wait
for (i=1; i<THREAD_COUNT; i++)
signal_sem (tCount[i]) ;
//signal
/* HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH */
pthread_mutex_lock(&stdoutLock) ;
cout << "\nAll children are now in position.\n" ;
cout << "Mother exiting ... \n\n" ;
pthread_mutex_unlock(&stdoutLock) ;
return ;
}
/* ################################################## */
/* main */
/* ################################################## */
int main()
{
cout << "\nWelcome to Diamond Heights!\n\n" ;
/* This calls the function that performs initializations. */
init();
/* Execute the mother() function */
mother();
return 0 ;
}
我尝试对母班的wait_sem()
进行检查,并在放置所有8个孩子后让她退出。但她不是,我的算法有问题吗?
该计划输出的内容:
Mother Begins Spawning Threads. Child # 0 is now in position. Child # 1 is now in position. Child # 2 is now in position. Mother Finishes Spawning Threads. Segmentation fault
我想要的是:
Mother Begins Spawning Threads. Mother Finishes Spawning Threads. Child # 0 is now in position. Child # 1 is now in position. Child # 2 is now in position. Child # 5 is now in position. Child # 4 is now in position. Child # 7 is now in position. Child # 3 is now in position. Child # 6 is now in position. Child # 8 is now in position. All children are now in position. Mother exiting ...
答案 0 :(得分:0)
你有
#define THREAD_COUNT 9
sim_semaphore tCount[THREAD_COUNT] ;
并且您的i
孩子访问
wait_sem (tCount[me*2+1]) ;
wait_sem (tCount[me*2+2]) ;
即。从4号子项开始,您将访问tCount
数组越界。要等待的tCount
数组元素的计算必须不同。请务必不要访问低于0且高于THREAD_COUNT+1
的元素。