发布订单是顺序的,因为创建调用按其编写的顺序发生。
但是,无论出于何种原因,调度程序都不是按您希望的顺序调度新启动的线程。如果订单很重要,线程可能不是你想要的?线程的一大优势是它们并不总是按顺序排列!
如果您确实想要使用同步原语(例如一系列互斥体或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'。 –