我在C中学习多线程,并且有些麻烦理解为什么我的代码没有给出预期的输出和段错误。我在C中使用了pthread库,我的代码启动了总共m * 2个线程,m为它启动的两个函数中的每一个。第一个函数计算30个随机数并将其存储在全局数组中。然后第二个函数从数组中读取整数,计算它们的总和及其平均值。第二个线程也等待第一个带有pthread_join的线程,但它似乎有时会在第一个线程退出之前连接。
我在这里做错了什么?
我也知道使用互斥锁会是一个更好的选择,但我会故意尝试使用互斥锁。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int n = 30;
int arr[100][30];
pthread_t tfirst[100];
pthread_t tsecond[100];
void *first(void *x){
for(int i = 0; i < n; i++)
arr[(int)x][i] = rand();
}
void *second(void *x){
pthread_join(tfirst[(int)x], NULL);
long sum = 0;
for(int i = 0; i < n; i++){
sum += arr[(int)x][n];
}
printf("Sum %d = %ld\n", (int)x + 1, sum);
sleep(1);
printf("Arithmetic mean %d = %f\n", (int)x + 1, (float)sum / n);
}
int main(int argc, char **argv){
int m;
srand(time(0));
if(argc < 2){
fprintf(stderr, "Usage: %s m [n]", argv[0]);
exit(EXIT_FAILURE);
}
m = atoi(argv[1]);
if(argc >= 3) n = atoi(argv[2]);
for(int i = 0; i < m; i++){
if (pthread_create(&tfirst[i], NULL, first, (void*)i)) {
fprintf(stderr, "Error creating thread!\n");
exit(EXIT_FAILURE);
}
if (pthread_create(&tsecond[i], NULL, second, (void*)i)) {
fprintf(stderr, "Error creating thread!\n");
exit(EXIT_FAILURE);
}
}
for(int i = 0; i < m; i++){
pthread_join(tfirst[i], NULL);
pthread_join(tsecond[i], NULL);
}
return 0;
}
答案 0 :(得分:4)
您为同一个帖子调用pthread_join
两次 - 首先在second
线程例程内,然后在main
结尾。
指定同一目标线程的多个同时调用pthread_join()的结果未定义。
如果pthread_join()的thread参数指定的值未引用可连接线程,则行为未定义。
部分“如果该线程已经终止,则pthread_join()立即返回”表示在已经结束但仍可加入的线程上调用pthread_join
会使调用返回但是,此调用后线程不再可以连接,再次调用pthread_join
将导致UB。
你的和计算代码是错误的:sum += arr[(int)x][n];
只会使用n
值(超出导致UB的界限)。
两个线程例程都应该返回一个值:return NULL;
答案 1 :(得分:1)
第二个线程也在等待第一个带有pthread_join的线程,但它似乎有时会在第一个线程退出之前加入。
实际上,第二个线程甚至可以在第一个线程之前开始执行。关于线程执行顺序没有任何保证。
解决方案是仅使用一个线程,即firts()
只需调用second()
。这将保证这些函数之间的执行顺序,而不需要任何互斥锁。