此代码用于同步问题,称为寿司栏问题。规则如下:
想象一下有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;
}
我在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;
}
伪代码如下所示:
// 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();
}