【问题标题】:Stumped on Semaphore algorithm难倒信号量算法
【发布时间】:2016-11-11 07:15:22
【问题描述】:

我被分配了一个程序来正确使用wait()signal() 函数作为信号量。任务是“隐喻地”创建一个菱形结构。 在纸面上,它会以分层方式看起来像这样

08 06 07 03 04 05 01 02 00 直到螺纹#06 和#07 都到位后,螺纹#08 才能加入金刚石。 在线程#04 和#05 都到位之前,线程#07 无法加入。 在线程#03 和#04 都到位之前,线程#06 无法加入。等等……

到目前为止,这是我的工作

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 个孩子后让她退出。但她不是,我的算法有问题吗?

这个程序输出什么:

母亲开始产卵。

孩子#0 现在就位。
1 号孩子现在就位。
2 号孩子现在就位。
母亲完成产卵线程。

分段错误

我想要的是:

母亲开始产卵。

母亲完成产卵线程。

孩子#0 现在就位。
1 号孩子现在就位。
2 号孩子现在就位。
5 号孩子现在就位。
4 号孩子现在就位。
7 号孩子现在就位。
3 号孩子现在就位。
6 号孩子现在就位。
8 号孩子现在就位。

现在所有孩子都已就位。
母亲退出...... 

【问题讨论】:

    标签: c++ algorithm semaphore


    【解决方案1】:

    你有

    #define THREAD_COUNT 9
    sim_semaphore tCount[THREAD_COUNT] ;
    

    和您的ith 孩子访问

    wait_sem (tCount[me*2+1]) ;
    wait_sem (tCount[me*2+2]) ;
    

    即从 4 号孩子开始,您将越界访问 tCount 数组。要等待的tCount 数组元素的计算必须不同。确保不要访问低于 0 和高于 THREAD_COUNT+1 的元素。

    【讨论】:

    • 好的,我不太确定您的建议是什么,您建议的更改是什么?我的计算不能正常工作吗?
    • 嗯,一开始你说,线程 8 必须在 7 和 6 上等待,7 在 4 和 5 上等待,依此类推。但是现在您的第 i 个线程等待线程 i*2+1 和 i*2+2。你必须找到一个更好的公式来模拟你想要的。您的段错误是由于公式错误并且您访问数组越界而导致的。
    • 好的,我现在明白了。我会试着想一个主意。另外,我的母亲类对应正确吗?
    • 你的母亲可以加入所有线程,而不是分离它们并等待它们的信号量,但你现在拥有的可能也可以工作。但似乎在孩子和母亲身上都对信号量 0 进行了特殊处理,我不确定这是否正确。
    • 在孩子中:if (me==0) { signal_sem (tCount[0]); }。在母亲中,关于信号量的循环从 1 开始。
    猜你喜欢
    • 1970-01-01
    • 2021-05-31
    • 1970-01-01
    • 2016-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多