2012-05-16 89 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 ..“奇怪”的解决方案后