[英]How to synchronize threads?
我在这段代码中使用了线程。 但是当我在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
您需要使用互斥量来避免竞争条件,并且还需要使用pthread_join在进程终止之前同步所有线程。
互斥体允许您在其中一个线程使用共享资源执行操作时停止某些线程(请参阅man pthread_mutex_lock,pthread_mutex_init)
pthread_join在你的代码中是必不可少的,因为它强制你的主线程等待你创建的其他线程,如果你不使用它,你不确定当主线程从main返回时所有线程都将完成。
有些人打印两次的原因(例如第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。 解决这个问题的方法是不将指针,而是j的值传递给线程构造函数。 更改pthread_create以传递值:
pthread_create(&tid, NULL, thread_operation, (void*) j);
并在您的线程中将值转换为线程参数:
int j =(int)arg;
从技术上讲,这依赖于int
和void*
在一般情况下它们不相同的事实。 但只要您没有使用巨型int
值,这将有效。
对于所有其他问题,@ Intrepidd使用pthread_join确保在所有线程完成之前进程不会退出。
使用线程之间不完整行的printf
通常不起作用。 您可能会完全损坏输出。 此外,行显示在屏幕上的顺序通常不是执行顺序,而是线程访问共享资源stdout
的顺序。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.