【问题标题】:making sure threads are created and waiting before broadcasting确保在广播之前创建线程并等待
【发布时间】:2011-12-13 21:15:38
【问题描述】:

我有 10 个线程应该等待信号。 到目前为止,我只是简单地完成了 'sleep(3)',并且工作正常,但是是否有更安全的方法来确保所有线程都已创建并且确实在等待。

我在关键区域进行了以下构造,在等待之前,增加一个计数器,告诉有多少线程正在等待。但是我必须有一个额外的互斥体和条件来向主发送所有线程都已创建的信号,这似乎过于复杂。

我是否缺少一些基本的线程设计模式?

谢谢 编辑:固定类型

编辑:澄清以下信息

在这种情况下,屏障不起作用,因为我不想让我的线程等到所有线程都准备好。 'cond_wait' 已经发生了这种情况。

我有兴趣让主函数知道,什么时候所有线程都准备好并等待。

//mutex and conditional to signal from main to threads to do work
mutex_t mutex_for_cond;
condt_t cond;

//mutex and conditional to signal back from thread to main that threads are ready
mutex_t mutex_for_back_cond;
condt_t back_cond;

int nThreads=0;//threadsafe by using mutex_for_cond

void *thread(){
    mutex_lock(mutex_for_cond);
    nThreads++;
    if(nThreads==10){
      mutex_lock(mutex_for_back_cond)
      cond_signal(back_cond);
      mutex_unlock(mutex_for_back_cond)
    }while(1){
      cond_wait(cond,mutext_for_cond);
      if(spurious)
        continue; 
      else
        break;
    }
    mutex_unlock(mutex_for_cond);
    //do work on non critical region data
}

int main(){
for(int i=0;i<10)
   create_threads;

while(1){
   mutex_lock(mutex_for_back_cond);
   cond_wait(back_cond,mutex_for_back_cond);
   mutex_unlock(mutex_for_back_cond);
   mutex_lock(mutex_for_cond);
   if(nThreads==10){
     break;
   }else{
     //spurious wakeup 
     mutex_unlock(mutex_for_cond);
   }
}
//now all threads are waiting
//mutex_for_cond is still locked so broadcast
cond_broadcast(cond);//was type here


}

【问题讨论】:

  • 您在此处展示的版本已经存在错误。 (1) 你正在阅读nThreads 而不持有锁。 (2) 在“虚假唤醒”的情况下,您解锁互斥锁两次。
  • 而且你的客户端也锁了两次。在尝试引入更多复杂性之前,您可能会尝试整理现有代码。
  • 1) nThreads 在哪里不受 mutex_for_cond 保护? 2)mutex_unlock如何在虚假唤醒的情况下被击中两次,while之后没有mutex_unlock(mutex_for_cond。

标签: c++ c multithreading thread-safety pthreads


【解决方案1】:

我是否缺少一些基本的线程设计模式?

是的。对于每个条件,都应该有一个受随附互斥锁保护的变量。条件变量上的信号仅指示此变量的变化。

您在循环中检查变量,等待条件:

mutex_lock(mutex_for_back_cond);
while ( ready_threads < 10 )
   cond_wait(back_cond,mutex_for_back_cond);
mutex_unlock( mutex_for_back_cond );

此外,您要构建的是线程屏障。它通常在线程库中预先实现,例如pthread_barrier_wait

【讨论】:

    【解决方案2】:

    明智的线程 API 有一个 barrier 结构,正是这样做的。

    例如,使用boost::thread,您将创建这样的屏障:

    boost::barrier bar(10); // a barrier for 10 threads
    

    然后每个线程都会在屏障上等待:

    bar.wait();
    

    屏障一直等到指定数量的线程在等待它,然后立即释放它们。换句话说,一旦所有十个线程都已创建并准备就绪,它将允许它们全部继续。

    这是简单而理智的做法。没有屏障构造的线程 API 需要您以艰难的方式完成,与您现在正在做的不同。

    【讨论】:

    • 线程中的障碍,不是我要找的。我希望 main 函数知道所有线程何时等待。
    • 那么为 11 个线程创建屏障,让主线程和 10 个辅助线程一起等待它?
    • 我的 main 启动了 10 个线程,当这些线程等待时,我的 main 应该会收到通知。如何启动 11 个线程并使用屏障信号返回到我的主线程,即 10/11 确实在等待?因为线程已经到达屏障,并不意味着它们已经到达 cond_wait
    • 移除条件变量。据我所知,屏障单独可以满足您的需求。
    【解决方案3】:

    您应该将一些包含“事件状态”的变量与条件变量相关联。主线程在发出广播之前适当地设置事件状态变量。对事件感兴趣的线程检查事件状态变量,不管它们是否阻塞了条件变量。

    使用这种模式,主线程不需要知道线程的精确状态——它只是在需要时设置事件然后广播条件。任何等待的线程都将被解除阻塞,任何尚未等待的线程将永远不会阻塞条件变量,因为它们会在等待条件之前注意到事件已经发生。类似于以下伪代码:

    //mutex and conditional to signal from main to threads to do work
    pthread_mutex_t mutex_for_cond;
    pthread_cond_t cond;
    int event_occurred = 0;
    
    void *thread() 
    {
        pthread_mutex_lock(&mutex_for_cond);
        while (!event_occurred) {
                pthread_cond_wait( &cond, &mutex_for_cond);
        }
        pthread_mutex_unlock(&mutex_for_cond);
    
        //do work on non critical region data
    }
    
    int main()
    {
        pthread_mutex_init(&mutex_for_cond, ...);
        pthread_cond_init(&cond, ...);
    
        for(int i=0;i<10)
            create_threads(...);
    
        // do whatever needs to done to set up the work for the threads
    
        // now let the threads know they can do their work (whether or not
        //  they've gotten to the "wait point" yet)
        pthread_mutex_lock(&mutex_for_cond);
        event_occured = 1;
        pthread_cond_broadcast(&cond);
        pthread_mutex_unlock(&mutex_for_cond);
    }
    

    【讨论】:

      猜你喜欢
      • 2021-08-09
      • 1970-01-01
      • 2022-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-15
      • 1970-01-01
      • 2011-05-10
      相关资源
      最近更新 更多