2015-10-31 64 views
0

我想开发一个C++软件,它有1个线程作为控制器(称为控制器)和8个其他线程(子线程)将通过TCP/IP发送/ recv。2线程同步,如何?

我的软件是在循环操作:

  • 在开始时,孩子线程无限循环中运行,在他们等待控制器START信号回路。如果他们通过来自控制器的信号唤醒,他们将执行发送/接收过程。信号发出后,控制器将等待来自子线程的停止信号。
  • 完成send/recv后,它们每个都会向控制器发送停止信号。如果控制器接收到足够的STop信号(8个子线程的8个停止信号)。它将复制数据,然后再次启动该过程(下一个循环)。

为此,我在一个非常基本的步骤中启动我的软件:控制器线程和一个子线程,并且此子线程不执行任何操作。 (如果一切正常,我会继续前进):

  • 换句话说,当子线程正在等待它时,控制器发送START信号给子线程。
  • 在收到START信号后,子线程发回STOP信号。

我首先执行这个软件1000次,有时它运行良好,有时不行,通常会冻结。

我想知道为什么会发生这种情况。

为了更好的说明,请参阅我的代码:

#include "CxxUtilities/CxxUtilities.hh" 
using namespace std; 
CxxUtilities::Condition StartSignal; 
CxxUtilities::Condition StopSignal; 

// declare a class of tx_thread, open, alive, wait for signal from controller thread // 
class ChildThread: public CxxUtilities::StoppableThread{ 
public: 
    void run(){ 
    cout << "started tx_thread" << endl; 
     while(!stopped){ 

     /* wait for signal from main thread */ 
     cout << "sub:wait for main..."; 
     StartSignal.wait(); 
     cout << "sub:done, \n"; 

     /* signal to main thread */ 
     StopSignal.signal();  
     cout << "sub:signal sent, \n"; 
    } 

    } 

}; 

int main(int argc, char* argv[]) { 
    using namespace CxxUtilities; 
    int i; 
    int Events = atoi(argv[1]); 

    // declear threads // 
    ReadingThread* thread[20]; 
    thread[0] = new ReadingThread; 
    thread[0]->start(); 
    usleep(1000); 

    for (i=0; i<Events; i++){ 
     cout << "\nevent#" << i+1 << ", "; 
     /* send start signal to sub thread */ 
     StartSignal.broadcast(); 
     cout << "main:signal sent, \n"; 

     /* wait for stop signal from sub thread */ 
     cout << "main:wait for sub ..."; 
     StopSignal.wait();  
     cout << "main:done, \n"; 
    } 
    cout << endl; 
} 

如果我修改这个软件只控制器的信号子线程或子线程只能信号给控制器,它工作正常。 当我们使用2个信号时,为什么线程会冻结?

在这个软件中,有使用2个文件被Thread.hhCondition.hh

这里是葛(在Condition.hh头文件中的一部分)和wait():

void signal(){ 
    mutex.lock(); 
    pthread_cond_signal(&condition); 
    mutex.unlock(); 

    void wait(){ 
    mutex.lock(); 
    pthread_cond_wait(&condition,mutex.getPthread_Mutex_T()); 
    mutex.unlock(); 
} 

回答

0

这是由于僵局而冻结。这种情况发生的一种方式是在条件设置之前主要调用StopSignal.wait并锁定互斥锁。然后你的子线程调用StopSignal.signal,这会阻塞等待互斥锁。所以两个线程都被阻塞,等待另一个线程的动作。

应该在最短的时间内获取锁。拥有锁的时候执行等待是需要麻烦的。你需要重组,所以等待没有锁。像

for (;;) { 
    mutex.lock(); 
    bool done = /*check condition variable*/; 
    mutex.unlock(); 
    if (done) break; 
    sleep(1); 
} 

这样的东西将保持锁定,当你访问受保护的条件变量,然后再释放它(允许条件的其他线程访问),而你检查条件的结果。睡眠在那里释放CPU资源。

这不是解决问题的唯一方法,但实现相当简单。

+0

对不起,我对你的解释感到困惑......让我来解释一下我的理解: - 主线程阻塞互斥体在子线程调用signal()之前调用wait()? - 正因为如此,互斥锁被锁定在主线程中,子线程无法锁定互斥锁来调用signal()? –

+0

@KhảiBùiTuấn没错。由于主线程获得了互斥锁,子线程阻塞(等待)互斥锁。 – 1201ProgramAlarm

+0

亲爱的@ 1201ProgramAlarm,你的意思是我们必须在wait()之前发信号()吗?如果那样的话,我认为这是没有道理的?它也在这里[链接](https://computing.llnl.gov/tutorials/pthreads/#ConditionVariables)中提到**在调用pthread_cond_wait()之前调用pthread_cond_signal()是一个逻辑错误。** –