- 使用同步机制确保任务队列并发访问安全
- 互斥锁(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);
}
- 可能出现的死锁情况及避免方法
- 死锁情况:
- 嵌套锁死锁:如果代码中有多个互斥锁,并且不同线程以不同顺序获取这些锁,就可能导致死锁。例如,线程A先获取互斥锁
mutex1
,然后尝试获取 mutex2
,而线程B先获取 mutex2
,然后尝试获取 mutex1
,这样就会形成死锁。
- 条件变量死锁:在使用条件变量时,如果没有正确处理互斥锁,也可能出现死锁。例如,在调用
pthread_cond_wait
前没有获取互斥锁,或者在 pthread_cond_signal
或 pthread_cond_broadcast
后没有释放互斥锁,都可能导致死锁。
- 避免方法:
- 统一锁获取顺序:对于多个互斥锁的情况,规定所有线程以相同顺序获取锁。例如,如果有
mutex1
和 mutex2
,所有线程都先获取 mutex1
,再获取 mutex2
。
- 正确使用条件变量和互斥锁:严格按照先获取互斥锁,再调用
pthread_cond_wait
;先调用 pthread_cond_signal
或 pthread_cond_broadcast
,再释放互斥锁的顺序进行操作。同时,在使用条件变量的等待循环中,确保条件判断是基于共享资源的状态,避免虚假唤醒导致的问题。