无法在C中具有pthread的线程之间拆分工作

问题描述 投票:0回答:1

我有一个使用pthread的C程序。我有一个全局链接列表结构和3个线程。每个线程都使用互斥体获得指向相同列表的指针,并尝试使它们一个接一个地工作。 (希望逐个线程)

由于某种原因,我得到一些奇怪的行为。首先,下面是代码:

void thread_function(node **list)
{
    int self_id = pthread_self();
    while (*list != NULL)
    {
        pthread_mutex_lock(&lock);
        printf("list location %p thread %u\n", *list, self_id);
        if (*list == NULL)
        {
            pthread_mutex_unlock(&lock);
            continue;
        }
        (*list)->result = result((*list)->num1, (*list)->num2);

        if (*list == NULL)
        {
            pthread_mutex_unlock(&lock);
            continue;
        }
        (*list) = (*list)->next;
        pthread_mutex_unlock(&lock);
    }
    pthread_cond_signal(&cv);
}

和输出(ubuntu终端)

./v2 nums.txt
list location 0x7fffc2fe76a0 thread 540870400
list location 0x7fffc2fe76c0 thread 540870400
list location 0x7fffc2fe76e0 thread 540870400
list location 0x7fffc2fe7700 thread 540870400
list location 0x7fffc2fe7720 thread 540870400
list location 0x7fffc2fe7740 thread 540870400
list location 0x7fffc2fe7760 thread 540870400
list location 0x7fffc2fe7780 thread 540870400
list location 0x7fffc2fe76a0 thread 532416256
list location (nil) thread 523962112
25 35  5
14 32  2
30 60  30
20 45  5
45 20  5
2254 54  2
236 65  1
21 20  1

在主要功能中,我创建了节点*list,并将&list赋予上述功能。

现在这是我的问题:

  1. 您只能看到一个线程完成了大部分工作,在不同的运行中,我可能在2个线程之间得到50-50,但第三个线程在做注释。

  2. 如果我删除第二个NULL检查(计算工作后),我将得到未定义的行为。我不明白为什么第二张支票会有所不同,如果它已经通过了第一张支票,则永远不要输入第二张支票。.?

  3. 最奇怪的事情发生在我删除线程ID和内存位置的打印时。 (只需删除printf行)。由于某种原因,程序被卡住。注意发生,注意打印(我在调用此函数后尝试打印结果),并且需要按Ctrl + C退出程序。我真的不知道为什么会这样。

我希望有人能对此主题有所启发,谢谢。

编辑:

在这里获得一些反馈后,我在while循环中进行了更改,并在之后检查了条件:

void thread_function(node **list)
{
    int self_id = pthread_self();

    while (1)
    {
        pthread_mutex_lock(&lock);
        printf("list location %p thread %u\n", *list, self_id);
        if (*list == NULL)
        {
            pthread_mutex_unlock(&lock);
            break;
        }
        (*list)->gcd = gcd((*list)->num1, (*list)->num2);
        if (*list == NULL)
        {
            pthread_mutex_unlock(&lock);
            break;
        }
        (*list) = (*list)->next;
        pthread_mutex_unlock(&lock);
    }
    pthread_cond_signal(&cv);
}

这仍然给出相同的结果。如果删除printf行,则会出现无限循环并注意打印,直到我用Ctrl + C中止该程序为止。如果我删除第二个检查,它仍然可以工作,但是我只能使用1个线程(mabye 50-50和另一个线程,但不是全部3个线程)

我还添加了调用它的主要功能。.我试图简化它

int main(int argc, char const *argv[])
{
    int pairs_count;
    node *list = create_numbers(argc, argv, &pairs_count);
    node *head = list;

    start_threads(&list);
    print_results(head);
}

void start_threads(node **list)
{
    pthread_t thread[NUM_THREADS];
    int status;

    for (int i = 0; i < NUM_THREADS; i++)
    {
        status = pthread_create(&thread[i], NULL, thread_function, list);
        if (status != 0)
        {
            fputs("pthread_create() error", stderr);
            exit(EXIT_FAILURE);
        }
    }
}

我知道create_numbers函数的工作原理,因为我尝试在调用列表后尝试打印列表,并且打印正确。这样列表就可以了。

c multithreading pthreads posix mutex
1个回答
0
投票

在我看来,您的主要问题是您没有保护while条件所进行的访问。这样会更好:

void thread_function(node **list)
{
    int self_id = pthread_self();

    while (1)
    {
        pthread_mutex_lock(&lock);
        if (*list == NULL)
        {
            pthread_mutex_unlock(&lock);
            break;
        }
        printf("list location %p thread %u\n", *list, self_id);
        (*list)->result= result((*list)->num1, (*list)->num2);
        (*list) = (*list)->next;
        pthread_mutex_unlock(&lock);
    }
    pthread_cond_signal(&cv);
}

而且,在循环结束时,在解锁后,您应该使用适当的值执行usleep()。否则,您的线程将自己占用处理器。

© www.soinside.com 2019 - 2024. All rights reserved.