【问题标题】:Unisex bathroom algorithm with priority男女通用浴室算法优先
【发布时间】:2016-09-23 13:19:06
【问题描述】:

我正在尝试制作 Semaphores and concurrent programming 中给出的中性浴室算法,那里的解决方案效果很好。但是我需要添加另一个功能,如果任何时候女性进入浴室,那么所有女性都必须在男性开始进入之前进入/离开浴室。

下面是 SO 的“信号量和并发编程”问题中另一个问题中没有优先功能的原始代码。

#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);
}

为了增加优先级,我添加了两个整数,left_men 和 left_women 来计算左侧男性和女性的数量。还有一个 int stopped_men 来检查我们是否早先停止了 msem。

int left_man, left_women, stopped_men;

void *woman(void *param)
{
    sem_wait(&z);
        sem_wait(&wsem);
            sem_wait(&y);
                left_women--;
                wcount++;
                if(wcount==1 && stopped_man == 0)
                {
                    stopped_man = 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 && left_women == 0 && stopped_man == 1)
        {
             sem_post(&msem);
             stopped_man = 0;
         }
    sem_post(&y);
}

在这种情况下,我遇到了死锁,因为如果“man”函数运行并获取“z”信号量而不是尝试获取“msem”信号量,但它无法获取,因为“女人”首先启动并停止它sem_wait(&msem) 通过将计数器减少到 0 并且在没有女人离开之前不会离开它,但是由于男人线程得到了“z”信号量,“女人”不能继续输入更多女人,所以“女人”等待“ z", man 等待 "msem" 所以我们陷入了僵局。

我也有想法改变“男人”功能如下,但这也会导致死锁,假设“男人”得到“msem”信号量而不是等待“z”信号量,因为第一个“女人”线程知道了,当 women 函数转到 sem_wait(&msem) 时,它将在那里停止,因为“msem”计数器较早从“man”函数减少。

sem_wait(&msem);
    sem_wait(&z);
        sem_wait(&x);
            mcount++;
            if(mcount==1)
            { sem_wait(&wsem); }
        sem_post(&x);
    sem_post(&z);
sem_post(&msem);

【问题讨论】:

  • 实际上我的算法与另一件事有关,而不是女性和男性,但为了方便起见,我参考了 SO 中已经存在的算法。
  • 你应该使用其他的东西。并非所有人都对男女通用的浴室有问题...
  • @stark 您如何将餐饮哲学家问题与这个问题联系起来?有什么提示吗?
  • 餐饮哲学家指的是资源冲突导致的死锁问题。

标签: c multithreading algorithm concurrency semaphore


【解决方案1】:

我找到了一个解决方案,它可能不是最好的,但它似乎有效。

sem_wait(&z);
if(stopped_man == 1)
{
    /* It means that someone stopped us, so release the "z" semaphore
       and wait for the thread that stopped us to signal us */
    sem_post(&z);

    sem_wait(&msem);
        sem_wait(&z);
            sem_wait(&x);
                mcount++;
                if(mcount==1)
                { sem_wait(&wsem); }
            sem_post(&x);
        sem_post(&z);
    sem_post(&msem);
}
else
{
        sem_wait(&msem);
            sem_wait(&x);
                mcount++;
                if(mcount==1)
                { sem_wait(&wsem); }
            sem_post(&x);
        sem_post(&msem);
    sem_post(&z);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-11
    • 1970-01-01
    • 2021-01-13
    • 1970-01-01
    • 2020-03-09
    • 1970-01-01
    相关资源
    最近更新 更多