如何在不使用信号量的情况下解决寿司吧问题?

问题描述 投票:2回答:2

Problem:

此代码用于同步问题,称为寿司栏问题。规则如下:

想象一下有5个座位的寿司吧。如果您在空座位时到达,您可以立即坐下。但是,如果你在所有座位都满了的时候到达,这意味着所有座位都在一起用餐,你必须等待整个派对在你坐下之前离开。

Script:

这里的代码使用信号量在C中工作。我一直试图写它没有信号量,但无济于事。它不必在C中,它可以是C ++或其他语言。

我在考虑条件变量,但我不确定如何实现它们。如果有人可以请求帮助,我真的很感激!

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

int eating = 0, waiting = 0;
bool must_wait = false;
sem_t block;                                                            
sem_t mutex;

void * sushiBar(void * threadID)
{
usleep(rand() % 1000);

sem_wait(&mutex);
if(must_wait){
    printf("Waits: %d seats are available. %d other people waiting.\n", 5-eating, waiting);
    waiting++;
    sem_post(&mutex);
    sem_wait(&block);
    waiting--;
}
if(eating == 4)
    printf("Last seat is taken.\n");
else{
    printf("%d seats available. Sits and eats sushi.\n", 5-eating);
}

eating++;
must_wait = (eating == 5);

if(waiting && (!must_wait))
    sem_post(&block);
else
    sem_post(&mutex);

usleep((rand() % 901) + 100);
sem_wait(&mutex);
eating--;
printf("Customer leaves: %d seats are available.\n", 5-eating);
if (eating == 0)
    must_wait = false;
if ( waiting && (!must_wait))
    sem_post(&block);
else
    sem_post(&mutex);
return 0;
}

int main(){
 int n=10,i=0,retVal=0;
 pthread_t *thread;

sem_init(&mutex, 0, 1);
sem_init(&block, 0, 0);

thread = (pthread_t *) malloc (n*sizeof(pthread_t));

for (i=0; i<n; i++){
  retVal = pthread_create(&thread[i], NULL, sushiBar, (void*)&i);
  if (retVal != 0){
    exit(EXIT_FAILURE);        
   }
}

for(i=0; i<n; i++){
    retVal = pthread_join(thread[i],NULL);
        if(retVal != 0){
           exit(EXIT_FAILURE);        
        }
 }

return 0;
}
c++ c synchronization semaphore condition-variable
2个回答
1
投票

我在C ++中使用condition_variable实现了这个问题(基本实现)。您可以使用它作为起点,并尝试开发您的应用程序

#include <iostream>           
#include <thread>             
#include <mutex>           
#include <condition_variable>

std::mutex mtx;
std::condition_variable cv;
int noofseats = 0;
bool ready = false;

void enter_bar(int id) {
    std::unique_lock<std::mutex> lck(mtx);

    while (noofseats  >= 5)
    {
        //lock threads if seats are filled
        cv.wait(lck);
        std::cout << "User :  " << id << "waiting for seat" << std::endl;

    }
    std::cout << "User :  " << id << "got seat" << std::endl;
    noofseats++;

}

void exit_bar()
{
    std::unique_lock<std::mutex> lck(mtx);
    noofseats--;
    if(noofseats < 5)
    {
        //would unloack other threads if seats are present
        cv.notify_all();
    }

}

int main()
{
    std::thread threads[10];
    // spawn 10 threads:
    for (int i = 0; i<10; ++i)
    {
        threads[i] = std::thread(enter_bar, i);
    }

    //three people exit bar
    exit_bar();       
    exit_bar();
    exit_bar();

    for (auto& th : threads) th.join();

    return 0;
}

0
投票

伪代码如下所示:

// global varaible
int seatsAtSushiBar = 5;

void
routineAtSushiBar()
{
    grabSeatAtSushiBar();
    haveLunch();
    releaseSeatAtSushiBar();
}

void
grabSeatAtSushiBar()
{
    // Get exclusive lock.
    condition_mutex->lock();
        while (0 == seatsAtSushiBar) {
            // Sleep while no seat available.
            condition_mutex->wait();
            // After wakeup you must check the conditon again, 
            // to protect from spurious wakeup calls.
        }
        // Seat is available grab one for yourself.
        seatsAtSushiBar--;
    condition_mutex->unlock();
}

void
releaseSeatAtSushiBar()
{
    // Get exclusive lock.
    condition_mutex->lock();
        // Release the seat.
        seatsAtSushiBar++;
        if (1 == seatsAtSushiBar) {
            // Wakeup a blocking customer to grab the seat.
            condition_mutex->notify();
        }
    condition_mutex->unlock();
}
© www.soinside.com 2019 - 2024. All rights reserved.