【问题标题】:How to determine which thread is done如何确定哪个线程已完成
【发布时间】:2017-09-12 10:57:19
【问题描述】:

我有一个调用pthread_join 的循环,但循环的顺序与线程终止的顺序不匹配。 我如何监控线程完成然后调用join?

for ( int th=0; th<sections; th++ ) 
{
    cout<<"start joining "<<th<<endl<<flush;
    result_code = pthread_join( threads[th] , (void**)&status); 
    cout<<th<<" join error "<<strerror(result_code)<<endl<<flush;
    cout<<"Join status is "<<status<<endl<<flush;
}

这是我的解决方案,它似乎通过提供第一个服务来最大化多线程吞吐量 完成线程。此解决方案不依赖于 pthread_join 循环顺序。

    // loop & wait for the first done thread

    std::bitset<Nsections> ready;
    std::bitset<Nsections> done;
    ready.reset(); 
    for (unsigned b=0; b<sections; b++) ready.flip(b);
    done = ready;

    unsigned currIdx = 1;       
    int th = 0;
    int th_= 0;
    int stat;

    while ( done.any() )
    {

        // main loops waiting for 1st thread to complete.
        // completion is checked by global vector
        // vStatus (singlton write protected)
        // and not by pthread_exit returned value,
        // in ordder to maximize throughput by 
        // post processig the first 
        // finished thread.

        if ( (obj.vStatus).empty() ) { Sleep (5); continue; }

        while ( ready.any() )
        {
            if ( sections == 1 ) break;

            if ( !(obj.vStatus).empty() )
            {
                if ( currIdx <= (obj.vStatus).size() )
                {
                    th_ = currIdx-1;

                    std::string s =
                    ready.to_string<char,std::string::traits_type,std::string::allocator_type>();
                    cout<<"checking "<<th_<<"\t"<<s<<"\t"
                        <<(ready.test(th_)?"T":"F")<<"\t"<<(obj.vStatus)[th_].retVal <<endl;        

                    if ((obj.vStatus)[th_].retVal < 1)
                    {
                        if (ready.test(th_))
                            { 
                            th=th_; 
                            ready.reset(th); 
                            goto retry;
                        }
                    }
                }
            }
            Sleep (2);

        } // while ready


        retry:
        cout<<"start joining "<<th<<endl<<flush;
        result_code = pthread_join( threads[th] , (void**)&status); 

        switch (result_code)
        {
            case EDEADLK: goto retry; break;
            case EINVAL:  
            case ESRCH:  
            case 0: 
                      currIdx++; 
                      stat = status->retVal;
                      free (status);
                      done.reset(th);

                      std::string s =
                    done.to_string<char,std::string::traits_type,std::string::allocator_type>();
                    cout<<"joined thread "<<th<<"\t"<<s<<"\t"
                        <<(done.test(th)?"T":"F")<<"\t"<<stat <<endl;

                      while (true)
                      {
                        auto ret=pthread_cancel ( threads[th] ) ;
                        if (ret == ESRCH) { netTH--; break; }
                        Sleep (20);
                      }
                      break;
        }

【问题讨论】:

  • 这可能需要您检查一些标志。为什么不使用更高级别的抽象,例如std::async 和任何其他产生std::future 的机制?见stackoverflow.com/questions/10890242/…
  • 当线程完成时设置一个布尔值。在主线程的循环中检查所述布尔值
  • 谢谢丹尼尔,但我认为 pthread_create 中的 arg 布尔变量在终止前没有更新
  • 如果 @WhiZTiMs 的建议由于某种原因不适合,您可能需要考虑删除 C++ 标记并明确声明您想要一个仅依赖于 POSIX 或 pthreads 的解决方案(视情况而定) )。

标签: c++ multithreading pthreads


【解决方案1】:

如何监控线程完成然后调用 join ?

通过让 join 检测完成。 (即什么都不做)

我有一个调用 pthread_join 的循环,但循环的顺序与线程终止的顺序不匹配。

循环的顺序无关紧要。

a) thread[main] 调用 thread[1].'join' 将被暂停,直到 thread[1] 退出。之后,thread[main] 将被允许继续循环的其余部分。

b) 当thread[2]thread[1] 之前终止时,thread[main] 调用thread[2].join 会立即返回。同样,thread[main] 继续。

c) 确保thread[1]thread[2] 之前终止(以匹配循环序列)的工作非常耗时,而且没有任何好处。

更新中...寻找我认为我已经提交的代码。

【讨论】:

  • “循环的顺序无关紧要” - 这取决于程序的要求。例如,执行连接的线程可能希望收集已完成线程的工作并在完成时对其进行处理(例如向用户显示中间结果),而不是阻塞可能长时间无法完成的任意线程。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-20
相关资源
最近更新 更多