2016-11-11 2 views
0

wait()signal() 기능을 세마포어로 올바르게 사용하도록 프로그램이 지정되었습니다. 임무는 "은유 적으로"다이아몬드 형성을 만드는 것입니다. 종이에 , 그것은Semaphore 알고리즘에 문제가 있음

 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

당신은

#define THREAD_COUNT 9 
sim_semaphore tCount[THREAD_COUNT] ; 

하고 i 번째 아이를이

wait_sem (tCount[me*2+1]) ; 
wait_sem (tCount[me*2+2]) ; 
0에 접근

즉 하위 번호 4부터 시작하여 범위 외의 tCount 배열에 액세스합니다. 대기 할 tCount 배열 요소의 계산은 달라야합니다. 0 이하 및 THREAD_COUNT+1 위의 요소에는 액세스하지 않아야합니다.

+0

좋습니다, 당신이 제안하는 것이 확실하지 않습니다. 제안 된 변경 내용은 무엇입니까? 계산이 제대로 작동하지 않습니까? – Junikin

+1

음, 처음에는 상태 8, 스레드 7과 6, 7과 4, 5에서 기다려야합니다. 하지만 이제 i 번째 스레드는 스레드 i * 2 + 1 및 i * 2 + 2에서 대기합니다. 당신이 원하는 것을 모델링하는 더 좋은 수식을 찾아야합니다. segfault는 수식이 잘못되어 배열을 벗어난 상태에서 액세스한다는 사실 때문에 생깁니다. –

+0

이제 알겠습니다. 나는 생각을하려고 노력할 것이다. 또한, 어머니 클래스가 정확하게 일치합니까? – Junikin

관련 문제