我正在尝试使用C语言和线程来解决睡觉的理发师问题。我写了一个主函数,还有线程控制的理发师和顾客函数。
由于某种原因,我的程序无法正常退出并在某处卡住或死锁。我的怀疑在于等待顾客的计数,因为从日志中可以看出,有些顾客来了,但没有得到服务。
我在这里附上我的代码。原型中列出的函数仅打印日志(*_service 除外,它等待 SERVICE_TIME)
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <stdbool.h>
#include <time.h>
#define CUSTOMERS 5
#define CHAIRS 1
#define SERVICE_TIME 100
#define MIN_INTERVAL 30
#define MAX_INTERVAL 80
// Values for the barber and customers synchronization
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t barber_available = PTHREAD_COND_INITIALIZER;
pthread_cond_t customer_waiting = PTHREAD_COND_INITIALIZER;
int waiting = 0; // Number of customers waiting
bool is_barber_sleeping = true;
// Prototype of functions
void *barber(void *arg);
void *customer(void *arg);
void barber_sleep();
void barber_service();
void customer_entry(int number);
void customer_wait(int number);
void customer_service(int number);
void customer_exit(int number);
void customer_reject(int number);
int served_customers = 0;
int rejected_customers = 0;
int main()
{
pthread_t barber_thread, customer_threads[CUSTOMERS];
srand((unsigned)time(NULL));
// Create barber thread
pthread_create(&barber_thread, NULL, barber, NULL);
// Simulate the arrival of customers
for (int i = 0; i < CUSTOMERS; i++)
{
pthread_create(&customer_threads[i], NULL, customer, (void *)(long)i);
int interval = (rand() % (MAX_INTERVAL - MIN_INTERVAL + 1) + MIN_INTERVAL);
usleep(interval * 1000); // Arrival of the next customer
}
// Wait for the end of the customer threads
for (int i = 0; i < CUSTOMERS; i++)
{
pthread_join(customer_threads[i], NULL);
}
// End of the barber thread
pthread_cancel(barber_thread);
pthread_join(barber_thread, NULL);
printf("Obsloužených zákazníků: %d\n", served_customers);
printf("Odmítnutých zákazníků: %d\n", rejected_customers);
return 0;
}
void *barber(void *arg)
{
while (true)
{
// If there are no customers, the barber sleeps
pthread_mutex_lock(&mutex);
while (waiting == 0)
{
barber_sleep();
is_barber_sleeping = true;
// The barber waits for the customer to wake him up
pthread_cond_wait(&customer_waiting, &mutex);
}
is_barber_sleeping = false;
waiting--;
pthread_mutex_unlock(&mutex);
// The barber serves the customer (wait for SERVICE_TIME)
barber_service();
pthread_cond_signal(&barber_available);
}
}
void *customer(void *arg)
{
int number = (int)(long)arg;
pthread_mutex_lock(&mutex);
customer_entry(number);
// If there is a free chair, the customer sits down
if (waiting < CHAIRS)
{
waiting++;
// If the barber is sleeping, the customer wakes him up
if (is_barber_sleeping)
{
pthread_cond_signal(&customer_waiting);
}
else
{
customer_wait(number);
}
pthread_mutex_unlock(&mutex);
pthread_mutex_lock(&mutex);
// Customer waits for the barber to be available
while (!is_barber_sleeping)
{
pthread_cond_wait(&barber_available, &mutex);
}
pthread_mutex_unlock(&mutex);
// Customer is served
customer_service(number);
served_customers++;
}
else
{
// If there are no free chairs, the customer leaves
pthread_mutex_unlock(&mutex);
customer_reject(number);
rejected_customers++;
}
customer_exit(number);
return NULL;
}
我尝试更改锁定功能。我期望根据问题定义得到正确的输出。 该技术来自我的学校项目: 只能使用pthread_mutex_t和pthread_cond_t进行同步,否则项目将无法评估。
理发师和顾客都先打电话
pthread_mutex_lock(&mutex);
才可以做任何事情。
如果我们假设理发师线程自创建以来首先被调度(这可能但不能保证),那么理发师将永远等待顾客发出信号
customer_waiting
但没有顾客可以到达这一点,因为mutex
已经被理发师锁住了。
这里可能还有其他错误,但马上肯定会陷入僵局。