【问题标题】:Multithreading in C not working properlyC中的多线程无法正常工作
【发布时间】:2012-07-05 21:45:33
【问题描述】:

所以我设法让我的程序运行,但由于某种原因,除非他/她之前的顾客先离开酒吧,否则没有顾客走进酒吧,我该如何解决? 我尝试了一个 mutex_lock,但我可能实施错了,这是我目前的代码:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>

sem_t sem;
pthread_mutex_t serve = PTHREAD_MUTEX_INITIALIZER;

void Bartender(int);
void EnterBar(int);
void OrderStart(int);
void ServeStart(int);
void ServeDone(int);
void OrderDone(int);
void DrinkBeer(int);
void LeaveBar(int);
void* Customer(void*);

void Bartender(int cid)
{
    ServeStart(cid);
    ServeDone(cid);
}

void* Customer(void* id)
{
    int cid =(int)id;
    EnterBar(cid);
    LeaveBar(cid);
    return NULL;

}

void EnterBar(int cid){
    sem_wait(&sem); //decrease semaphore
    printf("Customer %d enters the bar.\n", cid);
    int cups;

    for(cups=0;cups<(cid%3+1);cups++){
        pthread_mutex_lock(&serve);     
        OrderStart(cid);
        OrderDone(cid);
        DrinkBeer(cid);     
        pthread_mutex_unlock(&serve);
    }
}
void OrderStart(int cid)
{
    printf("Customer %d asks for beer.\n", cid);
    Bartender(cid);
}

void OrderDone(int cid)
{
    printf("Customer %d gets the beer.\n", cid);
}

void DrinkBeer(int cid)
{
    printf("Customer %d drinks the beer.\n", cid);
}

void LeaveBar(int cid)
{
    printf("Customer %d leaves the bar.\n", cid);
    sem_post( &sem ); //increase semaphore
}

void ServeStart(int cid)
{
    printf("Bartender starts to serve customer %d.\n", cid);
}

void ServeDone(int cid)
{
    printf("Bartender is done serving customer %d.\n", cid);
}

int main (int argc, char *argv[])
{
    int t;
    long rc;    
    int num_customers = atoi(argv[1]); //number of customers
    int capacity = atoi(argv[2]); //bar capacity

    if(num_customers > 0 && capacity > 0){
        rc = sem_init( &sem, 0, capacity );
        if (rc)
        {
            printf("ERROR; return code from sem_init() is %ld\n",rc);
            exit(-1);
        }
        //pthread_t threads[num_customers];
        pthread_t *threads = (pthread_t*)malloc(num_customers*sizeof(pthread_t));
        if(random() > RAND_MAX / 2)
            usleep(1);
        //rc = sem_init(&sem1,0,capacity);
        //rc = pthread_barrier_init(&barrier1, NULL, num_customers);
        for(t=0; t<num_customers;t++){
                printf("In main: creating thread %d\n", t);
            //printf("CAPACITY: %d\n", capacity);
                rc = pthread_create(&threads[t], NULL, Customer, (void* )t);
                if (rc){
                    printf("ERROR; return code from pthread_create() is %ld\n", rc);
                    exit(-1);
                }
        }
        for( t=0;t<num_customers;t++)
            pthread_join(threads[t],NULL);

        sem_destroy(&sem); //destroy semaphore
    }
    else{
            printf("ERROR: Both parameters should be a valid positive numbers.");
            exit(-1);
    }

    /* Last thing that main() should do */
    pthread_exit(NULL);
}

它应该允许酒吧里的多个顾客,并在喝完啤酒后离开,而不是在顾客离开之前离开。调酒师需要一根线吗? 有什么建议吗??

【问题讨论】:

  • 为我工作,编译并运行附加代码并得到: 客户 1 进入酒吧。在主要:创建线程 2 客户 0 离开酒吧。

标签: c linux multithreading synchronization pthreads


【解决方案1】:
#include <unistd.h>

并修改此功能

void DrinkBeer(int cid)
{
    printf("Customer %d drinks the beer for 10 seconds.\n", cid);
    sleep(10);
}
void LeaveBar(int cid)
{
    printf("Customer %d leaves the bar (takes 10 sec).\n", cid);
    sem_post( &sem ); //increase semaphore
   sleep(10);
}

看看它现在的表现。您需要一些睡眠功能,以便线程可以睡眠并更好地观察其他线程的工作方式。 修改后它是否可以正常工作?

【讨论】:

  • 不!这使得程序尽可能慢!
  • 修改是看它是否正常工作,不要留在最终代码中。这些函数执行得很快,以查看线程的行为方式。你意识到线程在执行这些函数时会休眠 10 秒,对吧?
  • 是的,确实如此,但这根本不能解决问题:/
【解决方案2】:

没有有你认为你有的问题。我做了以下更改。

(1) //添加全局变量

int count = 0;
pthread_mutex_t mutCount = PTHREAD_MUTEX_INITIALIZER;

(2) 添加到吧台人数统计并打印出来

void EnterBar(int cid)
{
    sem_wait(&sem); //decrease semaphore

    printf("Customer %d enters the bar.\n", cid);    

    pthread_mutex_lock(&mutCount);
    count++;
    printf("There are %i customers in the bar\n", count);
    pthread_mutex_unlock(&mutCount);

    int cups;

    for (cups = 0;cups < (cid % 3 + 1);cups++)
    {
        pthread_mutex_lock(&serve);
        OrderStart(cid);
        OrderDone(cid);
        DrinkBeer(cid);
        pthread_mutex_unlock(&serve);
    }
}

(3) 当他们离开时减少酒吧中的顾客数量

void LeaveBar(int cid)
{
    printf("Customer %d leaves the bar.\n", cid);

    pthread_mutex_lock(&mutCount);
    count--;
    pthread_mutex_unlock(&mutCount);

    sem_post( &sem ); //increase semaphore
}

(4) 在主要的变化中,睡觉去一些有价值的东西

    if (random() > RAND_MAX / 2)
        usleep(100);

(5) 我跑的是:barthread 20 15 | grep "有"

(6) 我得到以下输出:

There are 1 customers in the bar
There are 2 customers in the bar
There are 1 customers in the bar
There are 3 customers in the bar
There are 4 customers in the bar
There are 5 customers in the bar
There are 6 customers in the bar
There are 7 customers in the bar
There are 6 customers in the bar
There are 6 customers in the bar
There are 5 customers in the bar
There are 5 customers in the bar
There are 5 customers in the bar
There are 6 customers in the bar
There are 4 customers in the bar
There are 4 customers in the bar
There are 5 customers in the bar
There are 6 customers in the bar
There are 7 customers in the bar
There are 8 customers in the bar

【讨论】:

  • 出于某种原因,我在酒吧里一直只有 1 位顾客:/
  • 你在使用@amb下面提到的sleep(int)函数吗?
  • 不,我只是增加了睡眠计数。
  • 我将其更改为 1000,但速度仍然太快,因此一次只有 1 个客户在里面
  • 现在我看了一下,usleep 在代码中的位置毫无意义。在代码的线程部分中的某处放置一个 usleep(100) 。此外,您从不使用srandom(),因此您可能每次都获得相同的起始编号并且从不执​​行该语句。
【解决方案3】:

我认为这是正确的行为,对吧? 客户 2 是酒吧的第一个,但在客户 1 之后离开。

[amb@localhost ~]$ ./a.out 3 2
In main: creating thread 0
In main: creating thread 1
In main: creating thread 2
Customer 2 enters the bar.
Customer 2 asks for beer.
Bartender starts to serve customer 2.
Bartender is done serving customer 2.
Customer 2 gets the beer.
Customer 2 drinks the beer for 7 seconds.
Customer 1 enters the bar.
Customer 1 asks for beer.
Bartender starts to serve customer 1.
Bartender is done serving customer 1.
Customer 1 gets the beer.
Customer 1 drinks the beer for 8 seconds.
Customer 2 asks for beer.
Bartender starts to serve customer 2.
Bartender is done serving customer 2.
Customer 2 gets the beer.
Customer 2 drinks the beer for 6 seconds.
Customer 1 asks for beer.
Bartender starts to serve customer 1.
Bartender is done serving customer 1.
Customer 1 gets the beer.
Customer 1 drinks the beer for 4 seconds.
Customer 1 leaves the bar.
Customer 0 enters the bar.
Customer 0 asks for beer.
Bartender starts to serve customer 0.
Bartender is done serving customer 0.
Customer 0 gets the beer.
Customer 0 drinks the beer for 6 seconds.
Customer 2 asks for beer.
Bartender starts to serve customer 2.
Bartender is done serving customer 2.
Customer 2 gets the beer.
Customer 2 drinks the beer for 7 seconds.
Customer 0 leaves the bar.
Customer 2 leaves the bar.

【讨论】:

  • 是的,但是在用户进入酒吧之前,应该允许客户进入
  • 什么?你是说这条线吗?顾客 2 喝了 7 秒钟的啤酒。顾客 1 进入酒吧。顾客 1 没有等到 2 喝完酒才进入酒吧。
  • 你是对的,你只是在drinkbeer和leavebar中添加了睡眠?
  • void DrinkBeer(int cid) { int drinkTime = rand() % 10 + 1; printf("客户 %d 喝了 %d 秒的啤酒。\n", cid, drinkTime);睡眠(饮酒时间); }
  • void EnterBar(int cid){ sem_wait(&sem); //减少信号量 printf("客户 %d 进入酒吧。\n", cid);国际杯; for(cups=0;cups
【解决方案4】:

所有这些互斥锁是怎么回事?几个信号量有什么问题,一个'barAccess',初始化为条形容量,一个'barStaff',初始化。调酒师的数量?

#define slaughtered (beerCount==10)

{
  beerCount=0;
  wait(barAccess);
  do{
    wait(barStaff);
    sleep(pouringTime);
    signal(barstaff);
    sleep(drinkingTime);
    beerCount++;
  }while(!slaughtered);
  signal(barAccess);
};

如果此酒吧有常客,您可以添加另一个 while(true) 循环并使用“sleep(soberUp);”围绕它在 boozer 中的每个会话之后。

在营业时间内改变酒吧员工的数量也很容易。只需添加更多“barStaff”单位或偷走一些。

如果它真的很忙,您可能还想打开酒廊酒吧以增加容量 - 只是所有更多 barAccess 单元在一个循环中。

关门时间应该很有趣。你需要说服顾客离开,不要再让他们进来。如果顾客没有在合理的时间内得到服务,也许他们应该离开。然后,您可以吸走所有的酒吧员工,这样顾客就无法得到服务,并聚集在所有的 barAccess 单元中,这样新顾客就无法进入。最终,今天的酒吧将是空的。第二天开门时,先挤进酒吧工作人员,然后挤进吧台访问单位,然后看着抢餐!

【讨论】:

  • 好吧,客户在喝完他们应该喝的东西后离开(在这种情况下,他们的客户 ID 为 % 3 + 1 ),在他们喝完最后一杯啤酒后,他们应该离开。酒吧工作人员应该永远是一个,只有一个人会负责酒吧管理。容量应该在执行程序时从命令行参数中预定义。
猜你喜欢
  • 1970-01-01
  • 2013-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-17
  • 1970-01-01
相关资源
最近更新 更多