MST
星途 面试题库

面试题:C语言线程池任务队列的并发访问控制

在Linux C语言线程池模型的任务队列管理中,多个线程可能会同时访问任务队列(如一个线程往队列添加任务,另一个线程从队列取出任务)。请描述你会如何使用POSIX线程库中的同步机制(如互斥锁、条件变量)来确保任务队列的并发访问安全,并且分析可能出现的死锁情况及如何避免。
43.9万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试
  1. 使用同步机制确保任务队列并发访问安全
    • 互斥锁(Mutex)
      • 定义一个互斥锁变量,例如 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER
      • 在往任务队列添加任务的函数中,在访问任务队列相关操作(如添加新任务到队列数据结构)前,调用 pthread_mutex_lock(&mutex) 来获取互斥锁,操作完成后调用 pthread_mutex_unlock(&mutex) 释放互斥锁。示例代码如下:
void add_task(task_queue *queue, task *new_task) {
    pthread_mutex_lock(&queue->mutex);
    // 将新任务添加到队列的具体操作
    // 例如:queue->tasks[queue->tail++] = new_task;
    pthread_mutex_unlock(&queue->mutex);
}
 - 在从任务队列取出任务的函数中,同样在访问任务队列相关操作(如从队列中取出任务)前获取互斥锁,操作完成后释放互斥锁。示例代码如下:
task* get_task(task_queue *queue) {
    pthread_mutex_lock(&queue->mutex);
    task *ret_task = NULL;
    // 从队列中取出任务的具体操作
    // 例如:if (queue->head < queue->tail) { ret_task = queue->tasks[queue->head++]; }
    pthread_mutex_unlock(&queue->mutex);
    return ret_task;
}
  • 条件变量(Condition Variable)
    • 定义一个条件变量 pthread_cond_t cond = PTHREAD_COND_INITIALIZER
    • 当从任务队列取任务时,如果队列为空,线程需要等待有新任务加入。此时,线程调用 pthread_cond_wait(&cond, &mutex),这个函数会自动释放之前获取的互斥锁,并使线程进入等待状态。当有新任务加入队列时,添加任务的线程调用 pthread_cond_signal(&cond)pthread_cond_broadcast(&cond) 来唤醒等待的线程。唤醒后,pthread_cond_wait 函数会重新获取互斥锁。示例代码如下:
task* get_task(task_queue *queue) {
    pthread_mutex_lock(&queue->mutex);
    while (queue->head == queue->tail) {
        pthread_cond_wait(&queue->cond, &queue->mutex);
    }
    task *ret_task = queue->tasks[queue->head++];
    pthread_mutex_unlock(&queue->mutex);
    return ret_task;
}

void add_task(task_queue *queue, task *new_task) {
    pthread_mutex_lock(&queue->mutex);
    // 将新任务添加到队列的具体操作
    // 例如:queue->tasks[queue->tail++] = new_task;
    pthread_cond_signal(&queue->cond);
    pthread_mutex_unlock(&queue->mutex);
}
  1. 可能出现的死锁情况及避免方法
    • 死锁情况
      • 嵌套锁死锁:如果代码中有多个互斥锁,并且不同线程以不同顺序获取这些锁,就可能导致死锁。例如,线程A先获取互斥锁 mutex1,然后尝试获取 mutex2,而线程B先获取 mutex2,然后尝试获取 mutex1,这样就会形成死锁。
      • 条件变量死锁:在使用条件变量时,如果没有正确处理互斥锁,也可能出现死锁。例如,在调用 pthread_cond_wait 前没有获取互斥锁,或者在 pthread_cond_signalpthread_cond_broadcast 后没有释放互斥锁,都可能导致死锁。
    • 避免方法
      • 统一锁获取顺序:对于多个互斥锁的情况,规定所有线程以相同顺序获取锁。例如,如果有 mutex1mutex2,所有线程都先获取 mutex1,再获取 mutex2
      • 正确使用条件变量和互斥锁:严格按照先获取互斥锁,再调用 pthread_cond_wait;先调用 pthread_cond_signalpthread_cond_broadcast,再释放互斥锁的顺序进行操作。同时,在使用条件变量的等待循环中,确保条件判断是基于共享资源的状态,避免虚假唤醒导致的问题。