2012-05-16 115 views
2

我有4個線程來創建線程1,線程2,thread3和thread4:多線程啓動順序

pthread_create(thread1,NULL,thread_func1,NULL); 
pthread_create(thread2,NULL,thread_func2,NULL); 
pthread_create(thread3,NULL,thread_func3,NULL); 
pthread_create(thread4,NULL,thread_func4,NULL); 

看在調試,在源代碼中定義啓動的線程的順序是不一樣的。 有沒有解決方案可以用我可以定義的順序啓動線程?

+0

複製? http://stackoverflow.com/questions/10616406/multi-thread-launch-arrangement – Jay

+0

@Jay - 我想我傾向於同意他們是重複的,這一個是前面的一個輕微泛化,我的答案基本上只是這個答案的概括。奇怪的是,兩個如此相似的問題被問到如此接近...... – Flexo

+0

通常你不能從日誌文件中推斷出大部分執行順序,除非你在每一行上都有一個時間標記。IO是互斥的,所以線程以與鎖獲得相關的任意順序執行'printf'。 –

回答

1

這裏我用

#include <pthread.h> 
#include <stdio.h> 

static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; 
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; 
static bool wait = TRUE; 

void thread_sync() { 
    pthread_mutex_lock(&mut); 
    wait = FALSE; 
    pthread_cond_signal(&cond); 
    pthread_mutex_unlock(&mut); 
} 
void thread_wait_sync() { 
    pthread_mutex_lock(&mut); 
    if (wait==TRUE) 
    { 
     pthread_cond_wait(&cond,&mut); 
    } 
    wait = TRUE; 
    pthread_mutex_unlock(&mut); 
} 

void *thread1(void *d) { 
    thread_sync(); 
    while (1); // Rest of work happens whenever 
    return NULL; 
} 

void *thread2(void *d) { 
    thread_sync(); 
    while (1); 
    return NULL; 
} 

void *thread3(void *d) { 
    thread_sync(); 
    while (1); 
    return NULL; 
} 

void *thread4(void *d) { 
    while (1); 
    return NULL; 
} 

int main() { 
    pthread_t t1,t2,t3,t4; 
    pthread_create(&t1, NULL, thread1, NULL); 
    thread_wait_sync(); 
    pthread_create(&t2, NULL, thread2, NULL); 
    thread_wait_sync(); 
    pthread_create(&t3, NULL, thread3, NULL); 
    thread_wait_sync(); 
    pthread_create(&t4, NULL, thread4, NULL); 
    while(1) { 
    // some work 
    } 
} 
4

發佈訂單順序的,因爲創建調用按其編寫的順序發生。

但是,無論出於何種原因,調度程序都不是按您希望的順序調度新啓動的線程。如果訂單很重要,線程可能不是你想要的?線程的一大優勢是它們並不總是按順序排列!

如果您確實想要使用同步原語(例如一系列互斥體或condvar)來確保某個點以可預測的順序發生,但從該點開始,順序仍然會降至調度程序的奇思妙想。舉個例子的代碼保證每個線程將打印其ID在創建它們的順序:

#include <pthread.h> 
#include <stdio.h> 

static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; 
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; 

void sync_threads(const int num, int *cur) { 
    pthread_mutex_lock(&mut); 
    while (*cur != num) { 
    pthread_cond_wait(&cond, &mut); 
    } 
    // Do work that must happen in order here: 
    printf("Thread: %d\n", num); 
    ++*cur; 
    pthread_mutex_unlock(&mut); 
    pthread_cond_broadcast(&cond); 
} 

static int num = 1; 

void *thread1(void *d) { 
    sync_threads(1,&num); 
    while (1); // Rest of work happens whenever 
    return NULL; 
} 

void *thread2(void *d) { 
    sync_threads(2,&num); 
    while (1); 
    return NULL; 
} 

void *thread3(void *d) { 
    sync_threads(3,&num); 
    while (1); 
    return NULL; 
} 

void *thread4(void *d) { 
    sync_threads(4,&num); 
    while (1); 
    return NULL; 
} 

int main() { 
    pthread_t t1,t2,t3,t4; 
    pthread_create(&t1, NULL, thread1, NULL); 
    pthread_create(&t2, NULL, thread2, NULL); 
    pthread_create(&t3, NULL, thread3, NULL); 
    pthread_create(&t4, NULL, thread4, NULL); 
    while(1) { 
    // some work 
    } 
} 

我用while(1);模擬一些實實在在的工作發生。它通過一個互斥體來保護「當前」線程,即初始化的順序,然後創建一個讓睡眠/喚醒成爲可能的條件。它向所有線程廣播,然後檢查下一個是誰。您可以設計爲跳過廣播的系統,但這樣做會使事情變得複雜,而收益相對較小。

如果需要,您也可以在其他位置添加更多同步,但您同步事物的次數越多,首先有線程的點越少。

理想的情況下,如果事情需要他們應該做的事之前產卵線程,不盡快線程產卵,如預測的順序發生:

fixed_init_for_thread1(); 
fixed_init_for_thread2(); 
fixed_init_for_thread3(); 
fixed_init_for_thread4(); 

pthread_create(thread1,NULL,thread_func1,NULL); 
pthread_create(thread2,NULL,thread_func2,NULL); 
pthread_create(thread3,NULL,thread_func3,NULL); 
pthread_create(thread4,NULL,thread_func4,NULL); 

,使得由時間創建的線程你不關心哪一個實際上有機會首先運行。

+1

+1對於*「你同步的東西越少,首先有線程就越少。」* –

1

我不認爲你真的關心首先執行哪個線程。如果您只需要四個線程的唯一標識符,請檢查pthread_self。要擁有順序ID,請從線程內調用ID分配器;或者在調用pthread_create時生成ID並將其作爲用戶參數傳遞。

0
Move 'pthread_create(thread2,NULL,thread_func2,NULL);' into thread_func1() 
Move 'pthread_create(thread3,NULL,thread_func2,NULL);' into thread_func2() 
Move 'pthread_create(thread4,NULL,thread_func2,NULL);' into thread_func3() 

這是非常接近的其他問題,最近公佈的,只是作爲ERR ..「奇怪」的解決方案後