2011-03-08 366 views
1

我有兩個線程一和兩個。由它們各自的類在頭文件中定義。我想在第一個線程啓動時啓動第二個線程。在第一個產生的意外結果的構造函數中創建並啓動第二個線程。 我的頭文件「header.h」C++ qthread同時啓動2個線程

#ifndef HEADER 
#define HEADER 
#include <QtGui> 
class One:public QThread 
{ 
public: 
    One(); 
    void run(); 

}; 

class Two:public QThread 
{ 
public: 
    Two(); 
    void run(); 
}; 
#endif 

我的類文件「的main.cpp」

#include "header.h" 
#include<iostream> 
using namespace std; 

One::One() 
{ 
/* the output just hangs at thread two and does not get to thread one run */ 
Two b; 
b.start(); 
b.wait(); 

} 
void One::run() 
{ 
    cout<<"One run\n"; 
    int i=0; 
    for(;;) 
    { 

     i++; 
     cout<<"+++ "<<i<<endl; 
     if(i==10) 
      break; 
     sleep(3); 
    } 
} 

Two::Two() 
{ 

} 
void Two::run() 
{ 

    cout<<"Two run\n"; 
    int i=0; 
    for(;;) 
    { 

     i--; 
     cout<<"----- "<<i<<endl; 
     sleep(3); 
    } 
} 
int main(int argc,char* argv[]) 
{ 
    One a; 
    // Two b; 
    a.start(); 
    // b.start(); 
    a.wait(); 
    // b.wait(); 
    return(0); 

} 

這是我多麼希望輸出運行工作代碼。

編輯:改變了代碼,因此現在 兩個線程都正確 獨立

如何啓動與第一線沿第二個線程,而不會在主即明確地調用兩個。

int main(int argc,char* argv[]) 
{ 
    One a; 
    Two b; 
    a.start(); 
    b.start(); 
    a.wait(); 
    b.wait(); 
    return(0); 
} 

螺紋兩者的調用和處理應該由一個線程來完成..

+0

目前我所擁有的是兩個獨立運行的線程,它們分開啓動。我想要做的是在線程啓動時調用第二個線程。 – 2011-03-08 10:58:18

+0

而這沒有意義。該線程在您啓動時調用。即使您可以從一個線程* object *調用另一個線程* context *到另一個線程,您也無法調用 – Erik 2011-03-08 11:03:51

+0

@Erick我已更改了代碼。移除一個線程上下文的調用。我試過在線程的構造函數中調用線程2,這是否是錯誤的?因爲我似乎看不到線程的運行輸出。 – 2011-03-08 11:21:02

回答

6

我相信你可能誤解了一些線程的概念。這聽起來像你想要啓動兩個線程,然後從一個線程上下文做一個函數調用到另一個線程上下文,這不是線程的工作方式。

當你啓動這兩個線程時,它們彼此獨立執行。他們可以共享數據訪問權限,但不能像你想要的那樣交錯執行。如果你想一個線程上的另一個請求執行的東西,你有兩個決定兩件事情:

  • 使用哪種機制,信號從一個線程請求到其他
  • 請求的線程是否應該停止與等待「收據」,或者只是愉快地繼續,而另一個線程完成所要求的事情。

一個非常簡單的(而不是真正的安全,這只是說明的邏輯)機制,這樣做將使用兩個布爾變量信號的要求,如:

Thread one starts       | Thread two starts 
Thread one works       | Thread two loops checking a `bool DoSomething;` 
Thread one sets bool DoSomething   | 
Thread one loops waiting for DidSomething | Thread two beeps 
              | Thread two sets DidSomething 
Thread one continues working    | 

的事注意在線程上下文之間沒有「調用」。這兩個線程同時執行,並使用數據(兩個布爾)進行通信。

在現實世界的多線程中,您不得不擔心同時訪問數據。例如什麼如果兩個線程同時在雙核機器上嘗試將數據附加到同一列表中,則會發生。這兩個線程可能會看到相同的「列表指針末尾」,兩者都會創建一個新條目,兩者都會更新「列表指針末尾」。但其中一個改變會覆蓋另一個,最好的情況是你會有一些丟失的數據和內存泄漏,最糟糕的情況是你會崩潰。

這就是您使用「互斥」機制的地方:在訪問列表等共享資源之前,每個線程將獲取互斥鎖。互斥體的構建方式是一次只能有一個線程「擁有」它。如果線程一碰巧先獲取互斥鎖,它將繼續執行其列表更新,然後釋放互斥鎖。與此同時,其他線程試圖獲取互斥體將簡單地坐在那裏,Mutex :: acquire()調用將不會返回,直到線程完成互斥體。如果兩個線程的行爲都很好,並且在訪問共享列表之前獲取互斥體,則上述同時更新不會發生,並且在兩個線程都更新後,該列表將完全有效。

爲迴應意見:

您不能同時啓動兩個線程。最接近的做法是創建並從One :: run內啓動Two:

void One::run() 
{ 
    Two b; 
    b.start(); 
    cout<<"One run\n"; 
    int i=0; 
    for(;;) 
    { 

     i++; 
     cout<<"+++ "<<i<<endl; 
     if(i==10) 
      break; 
     sleep(3); 
    } 
    b.wait(); 
} 
+0

如果沒有適當的內存屏障或鎖定,將bools設置爲標記是不安全的。在Qt中,使用交叉線程信號會更好。 – bdonlan 2011-03-08 10:47:47

+0

您可能還想閱讀*條件變量*。它們允許一個線程阻塞,直到某個條件由另一個線程發出信號。這是一個空的'while'循環的替代方案,它將佔用不必要的CPU時間。有關詳細信息,請參閱http://doc.qt.nokia.com/4.7-snapshot/qwaitcondition.html。 – 2011-03-08 10:48:08

+0

不,它不是,因此是「*非常*簡單」的短語。意圖是說明線程之間的通信邏輯,而不是作者想在上下文之間進行調用。 – Erik 2011-03-08 10:49:08