【问题标题】:wait for all threads finishing one job then doing another等待所有线程完成一项工作,然后再做另一项工作
【发布时间】:2017-10-07 19:57:28
【问题描述】:

假设有NUM_TREADS 线程并且它们必须在执行job2() 之前完成job1()。如何保证这种情况发生,像这样:

void thread_func(void *arg)
{
    while(1) {
        job1();
        some_kind_of_waiting();
        job2();
    }
    return NULL;
}

信号量会像下面这样工作还是有其他/更好的解决方案?

{
    static int done;
    static sem_t semaphore;

    if(__sync_fetch_and_add(&done, 1) == THREAD_NUMS-1) {
        done = 0;
        for(i = 0; i < THREAD_NUMS-1; i++)
            sem_post(&semaphore);
    } else
        sem_wait(&semaphore);
}

谢谢。

【问题讨论】:

  • 这是一个 c 还是 c++ 的问题?答案取决于您使用的语言。
  • 您正在从 void 函数返回 NULL
  • 你可以使用 C++ std::future 吗?

标签: c++ c multithreading pthreads


【解决方案1】:

这正是 pthreads 屏障旨在解决的问题。使用NUM_THREADS 初始化屏障(在您的主函数中,在产生线程之前):

pthread_barrier_t barrier;

pthread_barrier_init(&barrier, NULL, NUM_THREADS);

并使用pthread_barrier_wait() 进行同步:

void *thread_func(void *arg)
{
    while(1) {
        job1();
        pthread_barrier_wait(&barrier);
        job2();
    }
    return NULL;
}

如果您还需要线程等到所有其他线程都强制job2() 之后,它们中的任何一个才能再次在job1() 上启动,您可以在屏障上添加第二个等待:

void *thread_func(void *arg)
{
    while(1) {
        job1();
        pthread_barrier_wait(&barrier);
        job2();
        pthread_barrier_wait(&barrier);
    }
    return NULL;
}

【讨论】:

  • 如何为后续循环重新初始化屏障?您是否需要第二个屏障,或者您可以使用重新初始化的第一个屏障,以使线程在 job2() 完成后和恢复 job1() 之前等待?
  • @JonathanLeffler:屏障不需要重新初始化。线程从屏障中释放后,屏障立即可供线程再次等待。
  • 感谢您的信息。
【解决方案2】:

您描述了一个通常称为barrier 的高级并发控制结构。 C++ 标准库没有实现屏障,尽管它一直是proposed,并有望在未来成为 C++ 标准库的一部分。

在标准库提供解决方案之前,您当然可以自己实现屏障(可以使用条件变量),使用platform specific threading APIwrapper library

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多