2014-10-19 63 views
0

我想創建一個數字,都必須等待所有線程被創建,纔可以執行任何操作不同的線程在pthread_create()的說法。這是一個大型計劃的一小部分,我只是試圖採取步驟。當每個線程被創建時,它立即被信號量阻塞。所有線程創建完畢後,我循環並釋放所有線程。然後,我希望每個線程都打印出它的線程號碼,以驗證它們全部等待。我只允許一個線程使用另一個信號量一次打印。問題與POSIX線程同步和/或通過

我遇到的問題是,雖然我創建線程#1-10,一個線程打印,這是#11。另外,有幾個線程說他們有與另一個相同的號碼。在傳遞線程ID時出現錯誤還是以某種方式在我的同步中出現錯誤?

下面是相關代碼:

//Initialize semaphore to 0. Then each time a thread is spawned it will call 
    //semWait() making the value negative and blocking that thread. Once all of the 
    //threads are created, semSignal() will be called to release each of the threads 
    sem_init(&threadCreation,0,0); 


    sem_init(&tester,0,1); 


    //Spawn all of the opener threads, 1 for each valve 
    pthread_t threads[T_Valve_Numbers]; 
    int check; 

    //Loop starts at 1 instead of the standard 0 so that numbering of valves 
    //is somewhat more logical. 
    for(int i =1; i <= T_Valve_Numbers;i++) 
    { 
     cout<<"Creating thread: "<<i<<endl; 
     check=pthread_create(&threads[i], NULL, Valve_Handler,(void*)&i); 
     if(check) 
     { 
      cout <<"Couldn't create thread "<<i<<" Error: "<<check<<endl; 
      exit(-1); 
     } 
    } 

    //Release all of the blocked threads now that they have all been created 
    for(int i =1; i<=T_Valve_Numbers;i++) 
    { 
     sem_post(&threadCreation); 
    } 

    //Make the main process wait for all the threads before terminating 
    for(int i =1; i<=T_Valve_Numbers;i++) 
    { 
     pthread_join(threads[i],NULL); 
    } 
    return 0; 



} 
    void* Valve_Handler(void* threadNumArg) 
    { 
     int threadNum = *((int *)threadNumArg); 
     sem_wait(&threadCreation);//Blocks the thread until all are spawned 

     sem_wait(&tester); 
     cout<<"I'm thread "<<threadNum<<endl; 
     sem_post(&tester); 
    } 

當T_Valve_Numbers = 10,一些示例輸出:

Creating thread: 1 
Creating thread: 2 
Creating thread: 3 
Creating thread: 4 
Creating thread: 5 
Creating thread: 6 
Creating thread: 7 
Creating thread: 8 
Creating thread: 9 
Creating thread: 10 
I'm thread 11 //Where is 11 coming from? 
I'm thread 8 
I'm thread 3 
I'm thread 4 
I'm thread 10 
I'm thread 9 
I'm thread 7 
I'm thread 3 
I'm thread 6 
I'm thread 6 //How do I have 2 6's? 

OR

Creating thread: 1 
Creating thread: 2 
Creating thread: 3 
Creating thread: 4 
Creating thread: 5 
Creating thread: 6 
Creating thread: 7 
Creating thread: 8 
Creating thread: 9 
Creating thread: 10 
I'm thread 11 
I'm thread 8 
I'm thread 8 
I'm thread 4 
I'm thread 4 
I'm thread 8 
I'm thread 10 
I'm thread 3 
I'm thread 9 
I'm thread 8 //Now '8' showed up 3 times 

「我線程......」打印10次,看起來像我的信號量讓所有線程通過。我只是不確定爲什麼他們的線程數目被搞砸了。

+0

傳的我,而不是它的地址的值,到線程。 – Kevin 2014-10-19 16:04:47

+0

正如我下面所說的,我必須傳遞一個'void *'類型,而我的編譯器不允許我直接從int中進行投射。我無法找到/想出任何其他方式。 – art3m1sm00n 2014-10-19 16:10:36

回答

5
check=pthread_create(&threads[i], NULL, Valve_Handler,(void*)&i); 
                  ^^ 

您正在傳遞線程啓動函數的地址ii在主循環中一直在變化,與線程函數不同步。一旦線程函數實際取消引用該指針,您就不知道i的值是什麼。

通行證在實際的整數,而不是一個指向局部變量,如果這是你永遠需要傳遞的唯一的事情。否則,使用所有參數創建一個簡單的struct,爲這些(每個線程一個)構建一個數組,並將每個線程傳遞一個指向其自己元素的指針。

例子:(假設你的線程索引從來沒有溢出的int

#include <stdint.h> // for intptr_t 

... 
check = pthread_create(..., (void*)(intptr_t)i); 
... 

int threadNum = (intptr_t)threadNumArg; 

更好/更靈活/不需要intprt_t可能不存在例如:

struct thread_args { 
    int thread_index; 
    int thread_color; 
    // ... 
} 

// ... 

struct thread_args args[T_Valve_Numbers]; 
for (int i=0; i<T_Valve_Numbers; i++) { 
    args[i].thread_index = i; 
    args[i].thread_color = ...; 
} 

// ... 

check = pthread_create(..., &(args[i-1])); // or loop from 0, less surprising 

一個忠告關於這個:儘管線程將使用它,那麼線程參數數組至少需要保持活動狀態。在某些情況下,對每個結構使用動態分配可能更好,將該指針(及其所有權)傳遞給線程函數(特別是如果要分離線程而不是加入它們)。

如果你打算在某個時候加入的線程,保持周圍以同樣的方式這些參數你保持在你的pthread_t結構。 (如果你正在創建並在同一功能的加入,堆棧通常是罰款了點。)

+0

我花了大概2個小時試圖讓我傳遞給我的線程。pthread_create要求我給它一個類型void *,如果我嘗試直接轉換我的int我,由於大小的差異,我得到一個編譯錯誤。這是我唯一能讓它不會對我大叫的唯一方法 – art3m1sm00n 2014-10-19 16:09:48

+1

'intptr_t'與'void *'具有相同的大小,所以你可以在這種情況下使用它。 (或'uintptr_t'。) – Mat 2014-10-19 16:11:17

+0

謝謝!這解決了它。希望我在昨天一直都在看的時候找到了解決方案。 – art3m1sm00n 2014-10-19 16:13:08