【问题标题】:Semaphores and concurrent programming信号量和并发编程
【发布时间】:2011-04-20 08:52:09
【问题描述】:

对于家庭作业,我需要编写以下场景。这将通过使用 BACI(即 C--)的信号量来完成

有 2 间男女皆宜的洗手间,每间可容纳 4 人。由于它是男女皆宜的,因此只有同性的人可以同时在洗手间,FIFO 并不重要。我脑子里有一个基本的“算法”来处理 4 个男人和 4 个女人的 1 个洗手间。但我不知道如何编码。任何帮助将不胜感激。这是我所拥有的。

Woman:

Check to see if there are any men in the restroom. If so "wait".
If no men check to see if there are 4 people. If so "wait".
If no men and not 4 use restroom. When leaving signal there is a vacancy.
If last woman signal the men if they are waiting if not signal the woman.


Man:

check to see if there are any woman in the restroom. if so "wait"
If no woman check to see if there are 4 people. If so "wait".
If no woman and not 4 use restroom. when leaving signal there is a vacancy.
if last man signal the women if they are waiting if not signal the men.

提供了这些附加说明

  • 使用随机 FOR 循环在适当的地方模拟时间的流逝。这可以通过使用延迟函数轻松完成:

    void Delay (void)
    { 
      int i;
      int DelayTime;
      DelayTime = random (DELAY);
      for (i = 0; i < DelayTime; i++):
    }
    
  • 其中 const int DELAY = 10 到 100 之间的某个数字。

  • 很好地打印和格式化输出,并以这样一种方式打印消息:通过读取输出,人们可以跟踪执行顺序。
  • 将进程设置为永远循环,并使用控制 C(或控制中断)停止您的程序。

【问题讨论】:

  • 没有。但它不能饿死。所以男人和女人必须公平地使用厕所。
  • 我不确定您是否担心饥饿,但我很确定您的算法存在饥饿问题。想象一下,当一个女人已经在浴室里时,一个男人出现了,而女人却源源不断地出现,这样浴室就永远不会空了。
  • 是的。这是我看到的问题之一,我需要帮助。饥饿。这个问题可以通过让每个女人给男人发信号,每个男人给女人发信号来解决吗?
  • 如何限制它,以便每当您在另一个性别的队列中达到 4 人时,您就可以切换性别。这样你的饥饿问题就解决了。
  • 这听起来是个好主意。我现在的问题是如何设置女人和男人的流程,以便 4 个人可以同时进入洗手间?我已经运行了我的程序,以便一次允许 1 个人进入洗手间,而不会出现死锁或饥饿。但洗手间一次可以有 4 个人。

标签: c concurrency semaphore


【解决方案1】:

适用于 4 个卫生间的 baci 代码:

 const int Delayx = 60;
   int i;
   int Mcount,Wcount;
   binarysem x,y,z,Wsem,Msem;
   semaphore cap;
   void Delay(void)
   {
    int DelayTime;
    DelayTime = random(Delayx);
    for (i = 0; i<DelayTime; i++);
     }

 void Woman(void)
   {
     wait(z);
     wait(Wsem);
     wait(y);
     Wcount++;
     if(Wcount==1)
       { wait(Msem);  }
       signal(y);
       signal(Wsem);
       signal(z);

       wait(cap);
       cout << "A Woman has entered Restroom"<<endl;
       Delay();
       cout << "A Woman has exited Restroom"<<endl;

       signal(cap);
       wait(y);
       Wcount--;
       if(Wcount==0)
         {signal(Msem);}

        signal(y);
        }

 void Man(void)
  {
     wait(z);
     wait(Msem);
     wait(x);
     Mcount++;
     if(Mcount==1)
       { wait(Wsem);  }
       signal(x);
       signal(Msem);
       signal(z);

       wait(cap);
       cout << "A Man has entered Restroom"<<endl;
       Delay();
       cout << "A Man has exited Restroom"<<endl;

       signal(cap);
       wait(x);
       Mcount--;
       if(Mcount==0)
         {signal(Wsem);}

        signal(x);
        }


void main()
{
Mcount=0;
Wcount=0;
initialsem(x,1);
initialsem(y,1);
initialsem(z,1);
initialsem(Wsem,1);
initialsem(Msem,1);
initialsem(cap,4);
cobegin
{
    Woman(); Woman(); Woman();
    Woman(); Woman(); Woman(); 
    Woman();
    Woman(); Man();  Man();
    Man(); Man(); Man(); Man();
    Man(); Man();
}
      }

【讨论】:

    【解决方案2】:

    由于您想知道how to code your algorithm for 1 restroom,我已经在 C 中完成了。将它转换为 C-- 将是一项相当简单的任务,因为所有信号量构造看起来都非常相似。

    根据你的回答,

    C: sem_wait()  C--: wait()
       sem_post()       signal()
       sem_t            semaphore()
       sem_init()       initialsem() 
    

    请记住,如上所述,我只解决了 1-restroom 的问题。由于这是家庭作业,我希望您自己将其扩展为 2-restrooms 形式。

    Readers-writers problem 到我们的“中性厕所”问题,我们使用以下全局变量:

    int mcount,wcount; // count of number of men/women in restroom
    sem_t x,y,z;       // semaphores for updating mcount & wcount values safely
    sem_t wsem,msem;   // semaphores to block other genders' entry  
    sem_t cap;         // capacity of the restroom
    

    将这些信号量和计数器合并到man 线程函数中,

    void *man(void *param)
    {           
        sem_wait(&z);                
            sem_wait(&msem);        
                sem_wait(&x);
                    mcount++;
                    if(mcount==1)   
                    { sem_wait(&wsem); } // first man in, make women wait
                sem_post(&x);
            sem_post(&msem);
        sem_post(&z);
    
        sem_wait(&cap);  //wait here, if over capacity
    
        printf("\t\tman in!\n");
        delay();
        printf("\t\t\tman out!\n");
    
        sem_post(&cap);  //one man has left, increase capacity
    
        sem_wait(&x);
            mcount--;
            if(mcount==0)
            {sem_post(&wsem);}  // no man left, signal women 
        sem_post(&x);
    }
    

    类似地,女性线程函数将mcount 替换为wcount,将msem 替换为wsem,将x 替换为y。只有zman 函数中保持原样,因此manwoman 线程在同一个公共信号量上排队。 (因此,代码总是具有类似FIFO的行为,这确保了公平/非饥饿

    完整代码如下:(编译使用gcc filename -lpthread

    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    #include <semaphore.h>
    
    int mcount,wcount;
    sem_t x,y,z,wsem,msem,cap;
    
    void delay(void)
    {
        int i;
        int delaytime;
        delaytime = random();
        for (i = 0; i<delaytime; i++);
    }
    
    void *woman(void *param)
    {
        sem_wait(&z);
            sem_wait(&wsem);
                sem_wait(&y);
                    wcount++;
                    if(wcount==1)
                    { sem_wait(&msem); }
                sem_post(&y);
            sem_post(&wsem);
        sem_post(&z);
    
        sem_wait(&cap);
    
        printf("woman in!\n");
        delay();
        printf("\twoman out!\n");
    
        sem_post(&cap);     
    
        sem_wait(&y);
            wcount--;
            if(wcount==0)
            { sem_post(&msem); }
        sem_post(&y);
    }
    
    void *man(void *param)
    {           
        sem_wait(&z);
            sem_wait(&msem);
                sem_wait(&x);
                    mcount++;
                    if(mcount==1)
                    { sem_wait(&wsem); }
                sem_post(&x);
            sem_post(&msem);
        sem_post(&z);
    
        sem_wait(&cap);
    
        printf("\t\tman in!\n");
        delay();
        printf("\t\t\tman out!\n");
    
        sem_post(&cap);
    
        sem_wait(&x);
            mcount--;
            if(mcount==0)
            {sem_post(&wsem);}
        sem_post(&x);
    }
    
    int main(void)
    {
        int i;
        srandom(60);
    
            mcount = 0;
            wcount = 0;
            sem_init(&x,0,1);  // for sem_init, initial value is 3rd argument
            sem_init(&y,0,1);
            sem_init(&z,0,1);
            sem_init(&wsem,0,1);
            sem_init(&msem,0,1);
            sem_init(&cap,0,4);  // eg. cap initialized to 4
    
            pthread_t *tid;
            tid = malloc(80*sizeof(pthread_t));
    
        // You can use your cobegin statement here, instead of pthread_create()     
        // I have forgone the use of pthread barriers although I suppose they would nicely imitate the functionality of cobegin. 
        // This is merely to retain simplicity.
    
        for(i=0;i<10;i++)
        {
            pthread_create(&tid[i],NULL,woman,NULL);
        }
        for(i=10;i<20;i++)
        {     
                pthread_create(&tid[i],NULL,man,NULL);
        }
        for(i=0;i<20;i++)
        {     
                pthread_join(tid[i],NULL);
        }
    
        return(0);
    }
    

    在转换为 2-restrooms 形式时,请记下您需要复制哪些信号量和计数器变量以满足所有条件。快乐信号

    【讨论】:

      【解决方案3】:

      这就是我所拥有的。这允许 1 人一次进入洗手间,而不会出现僵局或饥饿。我需要有关如何制作它的帮助,以便一次可以有 4 个人在洗手间。

      const int Delayx = 60;
      int i;
      semaphore max_capacity;
      semaphore woman;
      semaphore man;
      semaphore mutex;
      
      void Delay(void)
      {
          int DelayTime;
          DelayTime = random(Delayx);
          for (i = 0; i<DelayTime; i++);
      }
      
      void Woman(void)
      {
          wait(woman);
          wait(max_capacity);
          wait(mutex);
          cout << "A Woman has entered Restroom"<<endl;
          Delay();
          cout << "A woman has exited Restroom"<<endl;
          signal(mutex);
          signal(max_capacity);
          signal(man);
      }
      
      void Man(void)
      {
          wait(man);
          wait(max_capacity);
          wait(mutex);
          cout <<"A Man has entered the Restroom"<<endl;
          Delay();
          cout << "A man has exited the Restroom"<<endl;
          signal(mutex);
          signal(max_capacity);
          signal(woman);
      }
      
      void main()
      {
          initialsem(woman,1);
          initialsem(man,1);
          initialsem(max_capacity,4);
          initialsem(mutex,1);
          cobegin
          {
              Woman(); Woman(); Woman(); Woman(); Woman(); Woman(); Woman(); Woman(); Man();  Man(); Man(); Man(); Man(); Man(); Man(); Man();
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-11-17
        • 2023-03-27
        • 1970-01-01
        • 1970-01-01
        • 2023-03-13
        • 2013-07-04
        • 1970-01-01
        • 2014-08-16
        相关资源
        最近更新 更多