了解pthread锁和条件变量

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

我进行了有关C中线程,锁和条件变量的练习。我需要编写一个程序来获取数据,将其转换为链接列表,开始3个线程,每个线程为列表中的每个节点计算结果并打印主线程。 evreyone完成后的结果。

这是主要功能:

int thread_finished_count;

// Lock and Conditional variable
pthread_mutex_t list_lock;
pthread_mutex_t thread_lock;
pthread_cond_t thread_cv;

int main(int argc, char const *argv[])
{
    node *list;
    int pairs_count, status;
    thread_finished_count = 0;

    /* get the data and start the threads */
    node *head = create_numbers(argc, argv, &pairs_count);
    list = head; // backup head for results
    pthread_t *threads = start_threads(&list);

    /* wait for threads and destroy lock */
    status = pthread_cond_wait(&thread_cv, &list_lock);
    chcek_status(status);
    status = pthread_mutex_destroy(&list_lock);
    chcek_status(status);
    status = pthread_mutex_destroy(&thread_lock);
    chcek_status(status);

    /* print result in original list */
    print_results(head);

    /* cleanup */
    wait_for_threads(threads, NUM_THREADS);
    free_list(head);
    free(threads);

    return EXIT_SUCCESS;
}

请注意,create_numbers函数正常运行,并且列表按预期运行。

这里是启动线程和线程功能代码:

pthread_t *start_threads(node **list)
{
    int status;
    pthread_t *threads = (pthread_t *)malloc(sizeof(pthread_t) * NUM_THREADS);
    check_malloc(threads);

    for (int i = 0; i < NUM_THREADS; i++)
    {
        status = pthread_create(&threads[i], NULL, thread_function, list);
        chcek_status(status);
    }
    return threads;
}

void *thread_function(node **list)
{
    int status, self_id = pthread_self();
    printf("im in %u\n", self_id);
    node *currentNode;

    while (1)
    {
        if (!(*list))
            break;
        status = pthread_mutex_lock(&list_lock);
        chcek_status(status);
        printf("list location %p thread %u\n", *list, self_id);
        if (!(*list))
        {
            status = pthread_mutex_unlock(&list_lock);
            chcek_status(status);
            break;
        }
        currentNode = (*list);
        (*list) = (*list)->next;
        status = pthread_mutex_unlock(&list_lock);
        chcek_status(status);
        currentNode->gcd = gcd(currentNode->num1, currentNode->num2);
        status = usleep(10);
        chcek_status(status);
    }
    status = pthread_mutex_lock(&thread_lock);
    chcek_status(status);
    thread_finished_count++;
    status = pthread_mutex_unlock(&thread_lock);
    chcek_status(status);
    if (thread_finished_count != 3)
        return NULL;
    status = pthread_cond_signal(&thread_cv);
    chcek_status(status);
    return NULL;
}
void chcek_status(int status)
{
    if (status != 0)
    {
        fputs("pthread_function() error\n", stderr);
        exit(EXIT_FAILURE);
    }
}

注意,self_id用于调试目的。

我的问题

  1. 我的主要问题是关于分工。因此,每个线程都从全局链接列表中获取一个元素,计算gcd,然后继续获取下一个元素。仅当在while循环中解锁互斥锁后添加usleep(10)时,才能获得此效果。如果我不添加usleep,则FIRST线程将进入并执行所有工作,而其他线程将在所有工作完成后等待并进入。

[请注意!:我考虑过可能创建第一个线程的选项,直到创建第二个线程为止,第一个线程已经完成了所有作业。这就是为什么在创建evrey线程时使用usleep(10)添加“我在#threadID中”检查的原因。他们都进来了,但只有第一个工作在做所有工作。这是输出示例,如果我在互斥锁解锁后执行usleep(注意不同线程ID)

with usleep

./v2 nums.txt
im in 1333593856
list location 0x7fffc4fb56a0 thread 1333593856
im in 1316685568
im in 1325139712
list location 0x7fffc4fb56c0 thread 1333593856
list location 0x7fffc4fb56e0 thread 1316685568
list location 0x7fffc4fb5700 thread 1325139712
list location 0x7fffc4fb5720 thread 1333593856
list location 0x7fffc4fb5740 thread 1316685568
list location 0x7fffc4fb5760 thread 1325139712
list location 0x7fffc4fb5780 thread 1333593856
list location 0x7fffc4fb57a0 thread 1316685568
list location 0x7fffc4fb57c0 thread 1325139712
list location 0x7fffc4fb57e0 thread 1333593856
list location 0x7fffc4fb5800 thread 1316685568
list location (nil) thread 1325139712
list location (nil) thread 1333593856
...
normal result output
...

如果我在互斥锁锁定后注释掉usleep,那就输出了(注意相同的线程ID)无睡眠

  ./v2 nums.txt
im in 2631730944
list location 0x7fffe5b946a0 thread 2631730944
list location 0x7fffe5b946c0 thread 2631730944
list location 0x7fffe5b946e0 thread 2631730944
list location 0x7fffe5b94700 thread 2631730944
list location 0x7fffe5b94720 thread 2631730944
list location 0x7fffe5b94740 thread 2631730944
list location 0x7fffe5b94760 thread 2631730944
list location 0x7fffe5b94780 thread 2631730944
list location 0x7fffe5b947a0 thread 2631730944
list location 0x7fffe5b947c0 thread 2631730944
list location 0x7fffe5b947e0 thread 2631730944
list location 0x7fffe5b94800 thread 2631730944
im in 2623276800
im in 2614822656
...
normal result output
...
  1. 我的第二个问题是关于线程工作的顺序。我的练习要求我不要使用join来同步线程(仅在最后使用“空闲资源”),而是要理解使用该条件变量。

我的目标是每个线程将采用元素,进行计算,同时另一个线程将加入并采用另一个元素,而新线程将采用每个元素(或至少接近该元素)

感谢您的阅读,请提供帮助。

c linux pthreads mutex condition-variable
1个回答
1
投票

首先,您正在按住锁的同时进行gcd()工作...因此(a)

在任何时候,只有一个线程可以进行任何工作,尽管(b)
© www.soinside.com 2019 - 2024. All rights reserved.