我在将主线程同步到最近启动的子线程时遇到问题。如何等待启动线程执行初始化代码
我想要做的是:
- 主线程创建一个新的子线程和块
- 子线程启动并初始化(可能需要一些时间)
- 一旦子线程被初始化,主线程继续(与两个线程并行运行)
我第一次尝试是这样的:
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