2012-08-11 34 views
1

我是这些pthreads的新手。我写了一个程序,以便随机显示数字,而不是按顺序显示。我已经使用pthrea_join()方法。该程序如下:pthreads不是连续执行的

int cnt=0,i=1; 
pthread_t th[10]; 
int printmsg() 
{ 
    cnt++; 
    printf("thread no. %d\n",cnt); 
} 
void tosync() 
{ 
    if(i>0) 
    pthread_join(th[i-1],NULL); // <---here i am blocking the previous thread..       
    printmsg(); 
} 
void main(void) 
{ 
    pthread_create(&th[0], NULL,(void*)&tosync, NULL); 
    for(i=1;i<10; i++){ 
    pthread_create(&th[i],NULL, (void*) &tosync, NULL); 
    } 
    int y; 
    for(int i=0; i<10; i++) 
    pthread_join(th[i],NULL); 
    return; 
} 

不过我得到随机数字...... plzz。帮助

+1

看来你在访问全局变量'i'时有问题。从主线程(增量)以及工作线程。除此之外,你期望'th [0]'做什么?等待自己? – Xyand 2012-08-11 18:02:25

+0

对不起,我忘了编辑...即使现在我随机得到的数字 – nitish712 2012-08-12 07:51:03

回答

1

pthread_join(th [i-1],NULL)这行有一些问题。当你创建一个线程时,你会增加i的值。假设 创建第一个三线程操作系统切换第三线程启动和操作系统切换到主线程创建其余线程。在创建完所有线程后,我的值为10/ 现在假设OS切换到第三线程,然后等待10-1 =第9线程完成并且类似地继续。因此最终它总是随机打印。你的策略是错误的。

试试这个

int cnt=0,i=1; 
pthread_t th[10]; 
int printmsg() 
{ 
cnt++; 
printf(thread no. %d\n",cnt); 
} 
void tosync() 
{ 

printmsg(); 
} 
void main(void) 
{ 
pthread_create(&th[0], NULL,(void*)&tosync, NULL); 
for(i=1;i<10; i++){ 
pthread_create(&th[i],NULL, (void*) &tosync, NULL); 
pthread_join(th[i],NULL); // <---here i am blocking the previous thread.. 
} 

return; 
} 
1

toSync功能,您使用的是i值,问题是你不知道的toSync功能运行时,什么样的价值i了。

在极端情况下,它可能对所有线程的值为10,如果创建线程的循环在任何创建的线程运行之前就会运行,则会发生此情况。

干净的解决方案是将i值作为参数传递给pthread_create,并让toSync使用该值代替全局i。例如。

int *id = (int*)malloc(sizeof(int)); 
*id = i; 
pthread_create(&th[i],NULL, (void*) &tosync, id); 

其他事情要考虑:

  1. toSync需要特殊处理的线程ID为0,因为它没有任何的前身等待
  2. main最后的循环不应该在线程0-8上调用pthread_join,因为它们已经加入。在同一个线程调用pthread_join几次的结果是undefined
+1

使用'malloc'这是内存和CPU时间的主要浪费。只需将'i'转换为'void *'而不是取其地址,并在线程启动函数中将其重新转换为int。 – 2012-08-11 18:13:33

+0

@R啊,好点! – johlo 2012-08-11 18:15:17

+0

还要注意,这是浪费同步:在一个线程中调用'malloc',在另一个线程中调用'free'将始终有一些隐藏的同步成本获取内存并将其返回到空闲池以重用。 – 2012-08-11 18:22:25

1

正在发生的事情是,你tosync()方法使用全局变量i,而不是明知的i值当线程实际上是开始。如果你想通过i(或者这里指向前一个pthread_t的指针)到tosync,以便它实际上记得它应该加入哪个线程,你需要通过pthread_create来传递它,类似于;

void* tosync(void* ptr) 
{ 
    pthread_t* threadIndex = (pthread_t*)ptr; 
    if(threadIndex != NULL) 
     pthread_join(*threadIndex, NULL); // <---here i am blocking the previous thread..       
    printmsg(); 
} 

...in the loop... 

pthread_create(&th[i], NULL, tosync, &th[i-1]); 

这是最后一个参数给pthread_create将作为threadIndex在你的方法来传递,如果包含索引,每个线程都知道它的单独的索引。

+0

不错,你只需要小心第一个线程,所以'pthread_create'调用和'tosync'必须包含一些条件。 – 2012-08-11 21:04:50

+0

@JensGustedt好点。它应该足以检查NULL并让第一个线程继续传递NULL作为参数。修正了代码:) – 2012-08-11 21:52:55

+0

@Isaksson现在我清楚哪里出了问题... thanx :) – nitish712 2012-08-12 07:59:16

1

另一种方法:

#include <stdio.h> 
#include <pthread.h> 

struct threadData{ 
    int id; 
    pthread_t prev; 
}; 


void tosync(void *data) 
{ 
    struct threadData *td=data; 
    if ((*td).prev!=0){ 
     printf("%i waiting\n",(*td).id); 
     fflush(0); 
     pthread_join((*td).prev,NULL); // <---here i am blocking the previous thread..       
    } 
    printf("%i runnning\n",(*td).id); 
    fflush(0); 
    free(td); 
} 

int main(void) 
{ 
    int i; 
    struct threadData *td; 
    pthread_t nextThreadID=0; 
    for(i=0;i<10; i++){ 
     td=malloc(sizeof(struct threadData)); 
     (*td).prev=nextThreadID; 
     (*td).id=i; 
     pthread_create(&nextThreadID,NULL, (void*) &tosync, (void *)td); 
    } 
    pthread_join(nextThreadID,NULL); 
    return 0; 
} 
2

你应该通过东西到你的日常tosync让每个线程都知道它应该等待的线程。另外,第一个线程不应该等待任何人。如果您使用线程启动例程的正确签名,则可以传递参数。

void * tosync(void *arg) 
{ 
    pthread_t *me = (pthread_t *)arg; 
    if (me > th) pthread_join(me[-1],NULL); 
    printmsg(); 
    return 0; 
} 

main应返回int。现在循环已经简化了,因为启动例程不再需要强制转换。由于每个线程都已加入其前任,因此main线程只需要连接最后一个线程。

int main(void) 
{ 
    for(i=0;i<10; i++){ 
    pthread_create(&th[i],NULL, tosync, &th[i]); 
    } 
    pthread_join(th[9],NULL); 
    return 0; 
}