發佈訂單是順序的,因爲創建調用按其編寫的順序發生。
但是,無論出於何種原因,調度程序都不是按您希望的順序調度新啓動的線程。如果訂單很重要,線程可能不是你想要的?線程的一大優勢是它們並不總是按順序排列!
如果您確實想要使用同步原語(例如一系列互斥體或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);
,使得由時間創建的線程你不關心哪一個實際上有機會首先運行。
複製? http://stackoverflow.com/questions/10616406/multi-thread-launch-arrangement – Jay
@Jay - 我想我傾向於同意他們是重複的,這一個是前面的一個輕微泛化,我的答案基本上只是這個答案的概括。奇怪的是,兩個如此相似的問題被問到如此接近...... – Flexo
通常你不能從日誌文件中推斷出大部分執行順序,除非你在每一行上都有一個時間標記。IO是互斥的,所以線程以與鎖獲得相關的任意順序執行'printf'。 –