Как я могу решить проблему с суши-баром без использования семафоров? - PullRequest
2 голосов
/ 08 марта 2019

Проблема:

Этот код предназначен для проблемы синхронизации, известной как проблема с суши-баром. Правила действуют следующим образом:

Представьте себе суши-бар на 5 мест. Если вы приедете, пока есть Свободное место, вы можете немедленно сидеть. Но, если вы приедете, когда все места полны, это означает, что все они обедают вместе, и вы будете нужно подождать, пока вся группа уйдет, прежде чем сесть.

Сценарий:

Код здесь работает на 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;
}

Ответы [ 2 ]

1 голос
/ 08 марта 2019

Я реализовал эту проблему, используя condition_variable в C ++ (базовая реализация). Вы можете использовать его в качестве отправной точки и попытаться разработать ваше приложение

#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 голосов
/ 08 марта 2019

Псевдокод будет выглядеть так:

// 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();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...