2011-05-08 72 views
4

我在这段代码中使用了线程。但是当我在shell中执行此代码时,某些线程不打印此行。如何同步线程?

printf("\ti'm %dth thread:)", j); 
printf("\t%c %d %d %d \n", arr[j].op, arr[j].byte, seq, no_file); 

此外,甚至一些线程打印此行两次。这个过程发生了什么?以及如何重新组织此代码,以便线程完全打印一行?

#include <stdio.h> 
#include <stdlib.h> 
#include <fcntl.h> 
#include <sys/stat.h> 
#include <unistd.h> 
#include <string.h> 
#include <pthread.h> 
#include <errno.h> 

typedef struct {char op; int byte; int seq; int no_file; } ARRAY; 

ARRAY *arr; 

void *thread_operation(void *arg){ 
    int j =*((int*)arg); 
    seq = arr[j].seq; 
    int no_file = arr[j].no_file; 
    printf("\ti'm %dth thread:)", j); 
    printf("\t%c %d %d %d \n", arr[j].op, arr[j].byte, seq, no_file); 
} 

int main() 
{ 
    int err, j, i = 10; 
    long int tid; 
    arr = (ARRAY*)malloc(sizeof(ARRAY) * i); 
    srand(time(NULL)); 
    for (i = 0; i <= 10; i++){ 
     arr[i].op = 'r'; 
     arr[i].byte = (rand() % 10); 
     arr[i].seq = i; 
     arr[i].no_file = i + 10; 
} 

    for(j = 0; j < 10; j++){ 
     printf("creating %dth thread.....", j); 
     err = pthread_create(&tid, NULL, thread_operation, &j); 
     if(err != 0) 
     printf("%s\n", strerror(err)); 
     printf("%dth done\n", j); 
    } 

    return 0; 
} 

这是结果从我的电脑

creating 0th thread.....0th done 
creating 1th thread..... i'm 0th thread:) r 9 0 10 
1th done 
creating 2th thread..... i'm 2th thread:) r 3 2 12 
    i'm 2th thread:) r 3 2 12 
2th done 
creating 3th thread..... i'm 3th thread:) r 6 3 13 
3th done 
creating 4th thread..... i'm 4th thread:) r 9 4 14 
4th done 
creating 5th thread..... i'm 5th thread:) r 3 5 15 
5th done 
creating 6th thread..... i'm 6th thread:) r 2 6 16 
6th done 
creating 7th thread..... i'm 7th thread:) r 2 7 17 
7th done 
creating 8th thread.....8th done 
creating 9th thread..... i'm 8th thread:) r 6 8 18 
9th done 
    i'm 9th thread:) r 8 9 19 
    i'm 9th thread:) r 8 9 19 

回答

6

您需要使用互斥吨避免竞争状态,而且你还需要使用pthread_join完成所有线程的进程死掉之前同步。

互斥允许你停止某些线程,而其中之一是使用共享的ressource执行动作(见男人的pthread_mutex_lock,调用pthread_mutex_init)

在pthread_join是在代码中必不可少的,因为它迫使你的主线程等待你创建的其他线程,如果你不使用它,你不能确定当主线程从主线程返回时所有的线程都会完成。

+1

谢谢..为什么一些线程(在上例中,第9个线程)执行了两次? – manut 2011-05-08 11:30:31

+0

比赛条件可能会导致未定义的行为,请考虑验证我的答案:) – Intrepidd 2011-05-08 17:49:11

1

使用printf与线程之间的不完整行通常不会工作。您可能会完全损坏输出。另外,屏幕上显示的行的顺序通常不是执行顺序,而是线程访问共享资源stdout的顺序。

2

有些人打印出来的原因是两次(比如线程编号9),因为你正在传递一个指向你的循环变量的指针作为thread_operation的输入。

for(j = 0; j < 10; j++){ 
    err = pthread_create(&tid, NULL, thread_operation, &j);<---here 

是& j被最终被thread_operation间接引用:

void *thread_operation(void *arg){ 
    int j =*((int*)arg);<---here 

,但在这一点上环可能拥有先进和j的值(在线程中运行)将是什么Ĵ恰好是现在在循环中。解决这个问题的方法是不传递指针,而是将j的值传递给线程构造函数。改变你在pthread_create传递值:

pthread_create(&tid, NULL, thread_operation, (void*) j); 

,并在你的线程投值出线的说法:

int j =(int)arg; 

现在从技术上来说这依赖于一个事实,即intvoid*大小相同当他们通常不是。但是,只要你不使用巨大的值,这将工作。

对于所有其他问题@Intrepidd是正确的关于使用pthread_join来确保在所有线程完成之前该进程不会退出。

+0

+1关于指针:) – Intrepidd 2011-05-08 17:52:45