我在將主線程同步到最近啓動的子線程時遇到問題。如何等待啓動線程執行初始化代碼
我想要做的是:
- 主線程創建一個新的子線程和塊
- 子線程啓動並初始化(可能需要一些時間)
- 一旦子線程被初始化,主線程繼續(與兩個線程並行運行)
我第一次嘗試是這樣的:
typedef struct threaddata_ {
int running;
} threaddata_t;
void*child_thread(void*arg) {
threaddata_t*x=(threaddata_t)arg;
/* ... INITIALIZE ... */
x->running=1; /* signal that we are running */
/* CHILD THREAD BODY */
return 0;
}
void start_thread(void) {
threaddata_t*x=(threaddata_t*)malloc(sizeof(threaddata_t));
x->running=0;
int result=pthread_create(&threadid, 0, child_thread, &running);
while(!x->running) usleep(100); /* wait till child is initialized */
/* MAIN THREAD BODY */
}
現在我完全不喜歡這樣,因爲它強制主線程睡眠的時間可能超過必要的時間。 所以我做了第2次嘗試,使用互斥&條件
typedef struct threaddata_ {
pthread_mutex_t x_mutex;
pthread_cond_t x_cond;
} threaddata_t;
void*child_thread(void*arg) {
threaddata_t*x=(threaddata_t)arg;
/* ... INITIALIZE ... */
pthread_cond_signal(&x->x_cond); /* signal that we are running */
/* CHILD THREAD BODY */
return 0;
}
void start_thread(void) {
threaddata_t*x=(threaddata_t*)malloc(sizeof(threaddata_t));
pthread_mutex_init(&x->x_mutex, 0);
pthread_cond_init (&x->x_cond , 0);
pthread_mutex_lock(&x->x_mutex);
int result=pthread_create(&threadid, 0, child_thread, &running);
if(!result)pthread_cond_wait(&x->x_cond, &x->x_mutex);
pthread_mutex_unlock(&x->x_mutex);
/* MAIN THREAD BODY */
}
這似乎不是第一次嘗試(使用正確的信號,而不是我自己的滾動等待循環)更清醒,直到我發現,這包括競爭條件: 如果子線程已經足夠快地完成初始化(在主線程等待條件之前),它會使主線程死鎖。
我想我的情況並不罕見,所以必須有一個非常簡單的解決方案,但我現在看不到它。
+1:也用於防止虛假喚醒到'while()'循環。 – alk 2012-07-14 15:04:59
請注意,這與OP的兩種方法(第一種方法中的「usleep()」被pthread_cond_wait()替換)完全相同。 – caf 2012-07-15 13:08:15
請注意,第一種方法中的運行標記不受互斥鎖保護。 – 2012-07-15 14:11:45