如何处理线程退出的障碍

Posted

技术标签:

【中文标题】如何处理线程退出的障碍【英文标题】: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:

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

【问题讨论】:

甚至没有不优雅的方式:),你不能复制另一个障碍或在同一障碍上多次致电pthread_barrier_init 【参考方案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 个线程都没有“未完成”时终止

以上是关于如何处理线程退出的障碍的主要内容,如果未能解决你的问题,请参考以下文章

Cuda _sync 函数,如何处理未知的线程掩码?

线程池中断 任务如何处理

如何处理 NumPy 中的大整数?

离子2:如何处理硬件后退按钮,检查应用程序中退出的确认

PHP 中如何处理并发请求(使用线程、线程池或子进程)

如何处理从 Undertow 工作线程抛出的异常?