📜  进程同步中的睡眠理发师问题(1)

📅  最后修改于: 2023-12-03 15:12:20.046000             🧑  作者: Mango

进程同步中的睡眠理发师问题
问题描述

在一家理发店中,有三个理发师和若干个等待理发的顾客。理发师需要对顾客进行理发,但每个理发师只能同时为一个顾客服务。如果有多个顾客等待理发,则只能有一个顾客能够进入理发店等待理发。如果所有理发师都没有顾客可为其服务,则理发师需要睡眠并等待顾客的到来。

解法

基本思路

  1. 设置锁和条件变量。
  2. 设计线程函数。每个理发师对应一个线程函数,线程函数实现了理发师的工作流程:尝试获取锁,如果无法获得,则等待条件变量的唤醒信号;如果能够获得锁,则判断是否有客人,如果有则服务,没有则睡眠。
  3. 设计主函数。主函数负责初始化锁和条件变量,并创建三个理发师线程和若干个顾客线程。顾客线程的函数实现了随机到来的顾客入店等待服务的过程,每个顾客入店的时候需要尝试获取锁,如果锁已被理发师占用,则释放锁并等待条件变量的唤醒信号,否则占用锁并等待理发师服务。
  4. 运行程序,观察输出结果。

代码实现

初始化锁和条件变量
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
理发师线程函数
void *barber(void *arg) {
    char *name = (char *)arg;
    while (1) {
        pthread_mutex_lock(&mutex);
        if (waiting == 0) {
            printf("%s: Zzzzzz...\n", name);
            pthread_cond_wait(&cond, &mutex);
            printf("%s: Wake up!\n", name);
        }
        waiting--;
        seats++;
        printf("%s: Cutting hair now. (%d/%d)\n", name, waiting, seats);
        pthread_mutex_unlock(&mutex);
        sleep(1);
    }
    pthread_exit(NULL);
}
顾客线程函数
void *customer(void *arg) {
    pthread_t tid = pthread_self();
    pthread_mutex_lock(&mutex);
    if (seats == 0) {
        printf("Thread %lu: There is no seat. (waiting: %d)\n", tid, waiting);
        pthread_mutex_unlock(&mutex);
        return NULL;
    }
    waiting++;
    seats--;
    printf("Thread %lu: Sit down. (waiting: %d)\n", tid, waiting);
    pthread_mutex_unlock(&mutex);
    pthread_cond_signal(&cond);
    pthread_mutex_lock(&mutex);
    while (waiting) {
        pthread_cond_wait(&cond, &mutex);
    }
    printf("Thread %lu: Leave. (waiting: %d)\n", tid, waiting);
    pthread_mutex_unlock(&mutex);
    pthread_exit(NULL);
}
主函数
int main() {
    pthread_t tid1, tid2, tid3;
    pthread_t customers[15];
    int i = 0;
    int ret;
    ret = pthread_create(&tid1, NULL, barber, "Barber 1");
    if (ret != 0) {
        printf("Create barber 1 failed.\n");
        return -1;
    }
    ret = pthread_create(&tid2, NULL, barber, "Barber 2");
    if (ret != 0) {
        printf("Create barber 2 failed.\n");
        return -1;
    }
    ret = pthread_create(&tid3, NULL, barber, "Barber 3");
    if (ret != 0) {
        printf("Create barber 3 failed.\n");
        return -1;
    }
    while (1) {
        ret = pthread_create(&customers[i], NULL, customer, NULL);
        if (ret != 0) {
            printf("Create customer %d failed.\n", i);
            return -1;
        }
        sleep(1);
        i++;
        if (i == 15) {
            break;
        }
    }
    ret = pthread_join(tid1, NULL);
    if (ret != 0) {
        printf("Join barber 1 failed.\n");
        return -1;
    }
    ret = pthread_join(tid2, NULL);
    if (ret != 0) {
        printf("Join barber 2 failed.\n");
        return -1;
    }
    ret = pthread_join(tid3, NULL);
    if (ret != 0) {
        printf("Join barber 3 failed.\n");
        return -1;
    }
    return 0;
}
总结

本文介绍了进程同步中的睡眠理发师问题,并提供了基本思路和代码实现。在实现过程中,我们需要考虑多线程竞争资源的问题,通过设置锁和条件变量,保证线程安全。同时也要注意防止死锁的发生。在编写多线程程序时,我们需要综合考虑线程安全和程序的效率,选择合适的同步机制来保证线程安全的同时尽可能减少线程的等待时间。