【问题标题】:how to handle barriers with threads quitting如何处理线程退出的障碍
【发布时间】:2012-01-05 23:08:12
【问题描述】:

伪代码:

void * thread_start(void *arg) {
    while (1) {
        /* for each column. Only run columns the thread_num
           is assigned to */
        column_count = thread_num;
        for (; column_count < dim - 1; column_count+=threads) {
             /* do thread work for data chunk */
        }

        /* barrier */
        barrier_result = pthread_barrier_wait(barrier);

        if (not_finished == 0) {
            /* finished */
            break;
            /* break while loop, end thread.
               The barrier is now broken because it is no longer
               getting called by this thread */
        }

        /* we are not finished, loop around and 
           do thread work on next data chunk */
    }
}

我对障碍的问题是如何处理在其他线程之前结束的线程?

屏障意味着每个线程都必须等待其他线程。

有哪些技术可以确保所有线程同时结束?

我尝试继续循环,但忽略了“线程工作”,但在这种情况下,所有 8 个线程都完成了,并且没有明智的方法告诉线程“你都完成了,现在都可以退出”

编辑:

算法:

  1. 对一段数据运行操作
  2. 如果线程的数据段完成则终止。
  3. 障碍等待。
  4. 一个线程用一些新数据替换这条数据
  5. 重复 1。

编辑 2:

有没有什么优雅的方法可以用小一号的屏障覆盖屏障? (没有在屏障周围放置互斥锁)

【问题讨论】:

  • 甚至没有不优雅的方式:),你不能复制另一个障碍或在同一障碍上多次致电pthread_barrier_init。

标签: c pthreads barrier


【解决方案1】:

通过程序逻辑的本质,您可以确保线程同时结束。如果您的算法要求线程在不同的时间退出,那么屏障不是该具体算法的合适并发控制机制。

编辑:

您可以原子地增加“finished_count”并循环,而不做任何工作,除了参与屏障,而该数字小于屏障计数(使用适当的互斥锁保护对 finished_count 的读/写)。

编辑: 我不确定我是否理解你添加的描述,我只是根据你的原始代码写的,也许它对你有用:

int finished_count;

void * thread_start(void *arg) {
    int finished = 0;

    while (1) {

        if (finished) {
            pthread_mutex_lock (&finished_lock);
            if (finished_count == 8) {
                pthread_mutex_unlock (&finished_lock);
                break;
            }
            pthread_mutex_unlock (&finished_lock);
        } else {
            /* for each column. Only run columns the thread_num
               is assigned to */
            column_count = thread_num;
            for (; column_count < dim - 1; column_count+=threads) {
                /* do thread work for data chunk */
            }

            /* set "finished" as appropriate */

            /* Check if we have just finished.  */
            if (finished) {
                pthread_mutex_lock (&finished_lock);
                ++finished_count;
                pthread_mutex_unlock (&finished_lock);
            }
        }

        barrier_result = pthread_barrier_wait(barrier);
    }

    return 0;
}

编辑:

为了澄清我上面关于复制或重新初始化的评论,POSIX 说:

http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_barrier_init.html

如果调用 pthread_barrier_init() 并指定已初始化的屏障,则结果未定义。

和

只有屏障引用的对象才能用于执行同步。在调用 pthread_barrier_destroy() 或 pthread_barrier_wait() 时引用该对象的副本的结果是未定义的。

【讨论】:

  • 我用我的“算法”描述更新了这个问题。你有什么建议吗?
  • 你理解了这个问题。我必须保持一个完成的计数。另一种方法是用一个新的更小的屏障覆盖屏障。我不知道哪个性能更好。
  • 事实证明,而不是为“线程完成”保留一个计数器并等到它为 n。应该为“线程未完成”保留一个标志,并在 n 个线程都没有“未完成”时终止
猜你喜欢
  • 2021-10-30
  • 2019-08-01
  • 2011-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-14
  • 2014-06-25
相关资源
最近更新 更多