注意是否所有线程都在 pthread_cond_wait

Noticing if all threads are at pthread_cond_wait

我目前正在使用 POSIX 库并试用条件变量。 目前我正在使用一个队列来安排任务,如果有一个任务,一个线程使用 pthread_cond_signal 来唤醒一个正在等待 pthread_cond_wait 的线程。 然而,可能有一个点没有创建新任务,所以每个线程都在等待 pthread_cond_wait 并且程序卡在那里。

我是否注意到我的所有线程是否都在等待 pthread_cond_wait?我试过使用计数器和 leave 变量,但我没有让它工作。

我的代码看起来与此处的代码相似:https://code-vault.net/lesson/j62v2novkv:1609958966824 ,除了每个线程都在添加新任务(在 executeTask 中)而不是仅在主方法中添加它们。

编辑: 这是我上面网站的代码版本(正在为我加载:/)

#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>

#define THREAD_NUM 4

typedef struct Task
{
    int a, b;
} Task;

Task taskQueue[256];
int taskCount = 0;
// THIS VARIABLE IS ADDED
int moreTasks = 10;

pthread_mutex_t mutexQueue;
pthread_cond_t condQueue;

void executeTask(Task *task)
{
    usleep(50000);
    int result = task->a + task->b;
    printf("The sum of %d and %d is %d\n", task->a, task->b, result);

    // THIS PART IS ADDED 
    if (moreTasks > 0)
    {
        pthread_mutex_lock(&mutexQueue);
        moreTasks--;
        pthread_mutex_unlock(&mutexQueue);
        Task t = {
            .a = rand() % 100,
            .b = rand() % 100};
        submitTask(t);
    }
}

void submitTask(Task task)
{
    pthread_mutex_lock(&mutexQueue);
    taskQueue[taskCount] = task;
    taskCount++;
    pthread_mutex_unlock(&mutexQueue);
    pthread_cond_signal(&condQueue);
}

void *startThread(void *args)
{
    while (1)
    {
        Task task;

        pthread_mutex_lock(&mutexQueue);
        while (taskCount == 0)
        {
            pthread_cond_wait(&condQueue, &mutexQueue);
        }

        task = taskQueue[0];
        int i;
        for (i = 0; i < taskCount - 1; i++)
        {
            taskQueue[i] = taskQueue[i + 1];
        }
        taskCount--;
        pthread_mutex_unlock(&mutexQueue);
        executeTask(&task);
    }
}

int main(int argc, char *argv[])
{
    pthread_t th[THREAD_NUM];
    pthread_mutex_init(&mutexQueue, NULL);
    pthread_cond_init(&condQueue, NULL);
    int i;
    for (i = 0; i < THREAD_NUM; i++)
    {
        if (pthread_create(&th[i], NULL, &startThread, NULL) != 0)
        {
            perror("Failed to create the thread");
        }
    }

    srand(time(NULL));
    for (i = 0; i < 100; i++)
    {
        Task t = {
            .a = rand() % 100,
            .b = rand() % 100};
        submitTask(t);
    }

    for (i = 0; i < THREAD_NUM; i++)
    {
        if (pthread_join(th[i], NULL) != 0)
        {
            perror("Failed to join the thread");
        }
    }
    pthread_mutex_destroy(&mutexQueue);
    pthread_cond_destroy(&condQueue);
    return 0;
}

我现在的问题是,一段时间后 taskCount 始终为零,因此我的所有线程都在 startThread 方法中的 pthread_cond_wait(&condQueue, &mutexQueue);。 如果所有线程都在这个地方,我有什么办法注意到吗?如上文所述,如果已经尝试对当前正在等待的线程使用计数器(以及我计算正在工作的线程的版本),但我无法弄清楚如何在每个任务完成后停止所有线程。

如果您想知道有多少线程在等待条件变量,只需在进入等待模式之前增加一个全局计数器并在唤醒时减少它。有了它,您就会知道当前有多少线程正在等待。

例如

//global scope
int num_waiting_threads = 0;

//in function startThread
while (taskCount == 0)
{
    //if num_waiting_threads == THREAD_NUM, all threads are waiting
    ++num_waiting_threads;
    pthread_cond_wait(&condQueue, &mutexQueue);
    --num_waiting_threads;
}

由于你有固定数量的任务,在处理完每个任务后,每个线程迟早会等待新提交的任务。您的执行函数总共只会添加 10 个新任务(moreTasks 初始化为 10 并不断减少,如果该计数器为零,则不会提交更多任务)。

因此,你could/should使用pthread_cond_timedwait,自己醒来检查num_waiting_threads状态。如果所有线程都在等待,跳出循环,退出线程。