多线程任务问题?

各位大佬请教一个问题,当我实现任务队列时rpushTasksQueue始终要比我上限少一个,比如我设定的上限是3,然后他2执行完就结束了,求救

#include <stdio.h>
#include "config.h"
#include "queue.h"

// 初始化任务队列
void initTasksQueue(struct TasksQueue* queue) {
    for (int i = 0; i < MAX_THREADS; i++) {
        printf("[*] 初始化任务队列[%d]\n",i);
        queue->front[i][0] = queue->rear[i][0] = -1;
    }
}

// 获取任务队列总数
int getTasksQueueCount(struct TasksQueue* queue, int thread_id) {
    // 如果头指针和尾指针的值都等于-1,代表该队列为空
    if (queue->front[thread_id][0]  == -1 && queue->rear[thread_id][0] == -1) {
        return 0;
    }
    // 计算任务中的总数:(尾指针-头指针+最大任务数)%最大任务数,如:(1-0+2)%2
    printf("%d当前任务数%d\n",thread_id,(queue->rear[thread_id][0] - queue->front[thread_id][0] + MAX_TASKS_PER_THREAD) % MAX_TASKS_PER_THREAD);
    return (queue->rear[thread_id][0] - queue->front[thread_id][0] + MAX_TASKS_PER_THREAD) % MAX_TASKS_PER_THREAD;
}

// 获取负载最低队列id
int getIdleTasksQueueKey(struct TasksQueue* queue) {
    // 初始化最小值为,队列数据上限
    int min = MAX_TASKS_PER_THREAD;
    
    // 初始化线程id,-1代表没有空闲
    int task_thread_index = -1;
    
    // 循环便利最大线程数
    for (int i = 0; i < MAX_THREADS; i++) {
        // 接收每个线程的任务总数
        int count = getTasksQueueCount(queue, i);
        if (count == 0) {
            // 线程空闲时直接返回
            return i;
        }
        
        // 线程里任务总数低于上限,小于上一次最小值,则本线程优先级最高
        if (count < MAX_TASKS_PER_THREAD && count < min) {
            min = count;
            task_thread_index = i;
        }
    }
    
    // 返回线程id
    return task_thread_index;
}

// 入队
int rpushTasksQueue(struct TasksQueue* queue, struct Task* task, int thread_id) {
    // 检查当前队列是否为空,如果为空头指针和尾指针设置为0
    if (queue->front[thread_id][0] == -1 && queue->rear[thread_id][0] == -1) {
        queue->front[thread_id][0] = queue->rear[thread_id][0] = 0;
    }
    
    // 计算尾部指针移动后的位置:尾指针+1
    int nextRear = (queue->rear[thread_id][0] + 1) % MAX_TASKS_PER_THREAD;

    if (nextRear == queue->front[thread_id][0]) {
        printf("[*] 线程[%d]已满\n",thread_id+1);
        return 0;
    }

    // 数据写入
    queue->tasks[thread_id][queue->rear[thread_id][0]] = *task;
    
    // 移动指针
    queue->rear[thread_id][0] = nextRear;
    return 1;
}


// 出队
int lpopTasksQueue() {
    return 0;
}

  // 模拟添加数据
    for (int j = 0; j<5; j++) {
            printf("\n\n[*] 当前第[%d]轮检查\n",j+1);
            // 获取负载最低队列id
            int getIdleTasksQueueKeyResult = getIdleTasksQueueKey(&tasksQueue);
            printf("[*] 当前空闲线程[%d]\n",getIdleTasksQueueKeyResult+1);
            if (getIdleTasksQueueKeyResult == -1) {
                printf("[*] 当前没有空闲线程,稍后再试\n");
                continue;
            }
        
            struct Task task = {
                .order_number="wwww",    // 订单号
                .account="18210560183",            // 充值账号
                .location="重庆",            // 归属地
                .city="重庆",                    // 所属城市
                .face_value=100        // 面值
            };
            int rpushTasksQueueResult = rpushTasksQueue(&tasksQueue, &task, getIdleTasksQueueKeyResult);
            if (rpushTasksQueueResult == 1) {
                printf("[*] 订单[]加入线程[%d]\n",getIdleTasksQueueKeyResult+1);
            }
        }
阅读 431
avatarAI BotBETA
# 多线程任务问题

在多线程编程中,任务队列是一种常见的同步机制,用于在多个线程之间分配任务。然而,在使用任务队列时,可能会遇到一些问题,其中最常见的是"生产者-消费者"问题。

"生产者-消费者"问题是一种经典的并发问题,其中生产者产生数据并放入队列,消费者从队列中取出数据并处理。当生产者的速度大于消费者的速度时,队列可能会溢出,导致数据丢失或程序崩溃。同样,当消费者的速度大于生产者的速度时,队列可能会耗尽,导致生产者空闲而消费者仍在等待。

为了避免这些问题,可以使用一些同步机制来控制生产者和消费者的速度,例如使用条件变量、互斥锁或信号量等。此外,还可以使用循环缓冲区或固定大小的缓冲区来限制队列的大小,以避免队列溢出或耗尽。

在你的代码中,你已经使用了循环缓冲区来限制队列的大小。然而,你的代码中存在一个问题,即在入队操作时没有检查队列是否已满。当队列已满时,你的代码仍然尝试将任务加入队列,这可能会导致队列溢出。

为了解决这个问题,你可以在入队操作前添加一个检查队列是否已满的条件。如果队列已满,你可以选择等待一段时间再重试,或者将任务加入另一个队列或缓冲区,以等待有空闲线程时再处理。

另外,你的代码中还有一些可以改进的地方。例如,在出队操作时没有处理队列为空的情况,这可能会导致程序崩溃或出现其他错误。你可以在出队操作前检查队列是否为空,如果为空则等待一段时间或处理其他任务。
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进