【问题标题】:Working with pthreads and synchronization使用 pthread 和同步
【发布时间】:2018-11-18 21:28:40
【问题描述】:

我正在编写一个玩具程序来帮助我了解障碍的工作原理。在程序中,我让每个线程检查一个数组中的元素是否在另一个数组中。我能够让所有线程同时开始搜索,但我希望它们在过滤后全部相遇,以便正确地将任何数字添加到数组中。

如果不这样做,可能会将错误的数字添加到数组中。

编辑:有人建议我添加 pthread_barrier_wait(&after_filtering);在对 filter_threads 的调用中,这似乎起到了作用。现在我知道我必须在 main 和 filter 函数中添加一个等待调用,但我不太了解执行流程以及 main 中的等待调用如何工作。我知道线程函数中的等待可确保所有线程在继续之前到达该点,但不是在线程创建后立即发生吗?这意味着 nums 的值应该是 99 而不是 4、3、8、1?

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

pthread_barrier_t before_filtering, after_filtering;
int nums[4] = {99, 99, 99, 99};
int arr[15] = {12, 5, 31, 8, 1, 6, 24, 4, 81, 42};

void filter(int i, int a[]){
    // Loop through the list
    int j;
    for (j = 0; j < 10; j++)
    {
        if (nums[i] == a[j])
            nums[i] = 0; 
    }
}

void *filter_threads(void *id){
    int *myid = (int *)id;
    printf("thread %d\n",*myid);
    pthread_barrier_wait(&before_filtering);
    filter(*myid, arr);
    pthread_barrier_wait(&after_filtering);
}

int main(void)
{
    pthread_t tids[3];
    int index[3];
    pthread_barrier_init(&before_filtering, NULL, 4);
    pthread_barrier_init(&after_filtering, NULL, 4);
    int i, j;

    for (i = 0; i < 3; i++)
    {   
        index[i] = i + 1;
        pthread_create(&tids[i], NULL, filter_threads, &index[i]);
    }

    // Cannot call any filter function without first populating nums
    nums[0] = 4;
    nums[1] = 3;
    nums[2] = 8;
    nums[3] = 1;

    pthread_barrier_wait(&before_filtering);
    filter(0, arr);
    pthread_barrier_wait(&after_filtering);

    // Add new numbers to arr...

    printf("New nums: ");
    for (i = 0; i < 4; i++)
        printf("%d, ", nums[i]);
    printf("\n");

    for (i = 0; i < 3; i++)
        pthread_join(tids[i], NULL);

    // Print new arr...

    pthread_barrier_destroy(&before_filtering);
    pthread_barrier_destroy(&after_filtering);
}

我尝试在过滤后添加另一个等待调用,但现在程序只是挂起。我怎样才能做到这一点?

【问题讨论】:

  • @fpea 您应该使用添加的附加代码更新您的问题。
  • @fpea 你的问题到底是什么,你想用这个程序完成什么?主线程算作一个线程,只要您的总线程数(包括主线程)等于您针对某个条件对barrier_wait 的调用次数,一切都会运行。现在您已将附加呼叫添加到barrier_wait,您应该完成了。线程将等待 3 秒让 main 进行第四次也是最后一次调用 barrier_wait,因此它们不会按照您的建议立即执行。

标签: c multithreading pthreads pthread-barriers


【解决方案1】:

屏障只是一种机制,可确保所有 N 个线程在继续之前到达代码中的某个点。因此,如果您调用 pthread_barrier_init 时计数为 4,则在同一屏障上调用 pthread_barrier_wait 的任何线程都不会继续,直到三个 other 线程也调用了 pthread_barrier_wait

因此,正如您的代码现在提供的那样:三个创建的线程一旦启动,将执行pthread_barrier_wait(&amp;before_filtering),它们将全部阻塞,直到主线程执行sleep(3),然后初始化nums 数组。然后主线程调用pthread_barrier_wait(&amp;before_filtering)。这会释放主线程和所有其他线程以继续执行。

在执行filter函数后,每个子线程主线程都应该执行pthread_barrier_wait(&amp;after_filtering)。否则,主线程将停止等待其他三个线程在屏障上等待。

话虽如此,根本不需要使用第二道屏障。此时,主线程实际上只是在等待其他三个线程完成任务并退出。由主线程完成的每个子线程上的pthread_join 完成了同样的事情:即线程上的pthread_join 在该线程完成执行之前不会返回。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-30
    • 1970-01-01
    • 1970-01-01
    • 2012-08-28
    • 2014-03-18
    • 2019-08-12
    相关资源
    最近更新 更多