线程数组中的第一个线程在 c 中被跳过(有时)?
First threads in array of threads getting skipped in c (sometimes)?
我正在尝试用 C 编写一个多线程程序,通过将数组分成多个分区来对数组进行排序,然后每个线程在它自己的分区上工作。问题似乎是有时会跳过线程 1,有时会跳过线程 2。我什至没有进行排序,只是进行比较。现在我只想知道我的线程 运行 是否正确,但似乎第一个线程无法安排或其他什么。我对 C 不是很擅长,并且真的在绞尽脑汁想出什么问题。
我知道调度程序可以暂停每个线程,但它们最终都应该完成,对吧?那么为什么我的前几个线程有时不是 运行?
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <time.h>
#define SIZE 11
#define HM_SORTERS 4
void * sort(void * param);
void printArr(int * arr);
struct PartitionBounds {
int tid;
size_t start;
size_t end;
};
int array[SIZE] = {18, 12, 68, 59, 75, 73, 68, 4, 16, 94, 15};
int main() {
// srand(time(NULL));
// for (size_t i = 0; i < SIZE; i++) {
// array[i] = rand() % 100;
// }
printArr(array);
pthread_t sorters[HM_SORTERS];
for(int i=0;i<HM_SORTERS;i++) {
struct PartitionBounds bounds;
size_t coverage = SIZE / HM_SORTERS;
bounds.tid = i;
bounds.start = i * coverage;
bounds.end = i + 1 == HM_SORTERS ? SIZE - 1 : bounds.start + coverage - 1;
int status = pthread_create(&sorters[i], NULL, sort, &bounds);
if(status == 0) {
printf("\n--- Thread %d created successfully ---\n", i + 1);
printf("start: %zu, end: %zu\n", bounds.start, bounds.end);
} else {
printf("!!! Failed to create thread !!!\n");
return 0;
}
}
for(int i=0;i<HM_SORTERS;i++) {
pthread_join(sorters[i], NULL);
}
printf("\n\n----- Sorting completed -----\n\n");
return 0;
}
void * sort(void * param) {
struct PartitionBounds *bounds = param;
printf("\n\tin thread %d\n\n", bounds->tid + 1);
for(size_t i=bounds->start;i<=bounds->end;i++) {
for(size_t j=i+1;j<=bounds->end;j++) {
if(array[j] < array[i]) {
printf("Thread %d: %d is smaller than %d\n", bounds->tid + 1, array[j], array[i]);
}
}
}
pthread_exit(NULL);
}
void printArr(int * arr) {
int coverage = SIZE / HM_SORTERS;
for(int i=0;i<HM_SORTERS;i++) {
size_t partitionEnd = i + 1 == HM_SORTERS ? coverage + SIZE % HM_SORTERS : coverage;
for(int j=0;j<partitionEnd;j++) {
printf("%d", array[j + coverage * i]);
if(j+1 < partitionEnd) {
printf(", ");
}
}
if(i+1 < HM_SORTERS) {
printf(" | ");
}
}
printf("\n");
}
输出:(典型,当线程被跳过时)
18, 12 | 68, 59 | 75, 73 | 68, 4, 16, 94, 15
--- Thread 1 created successfully ---
start: 0, end: 1
--- Thread 2 created successfully ---
start: 2, end: 3
in thread 1
--- Thread 3 created successfully ---
Thread 3: 73 is smaller than 75
in thread 3
Thread 3: 73 is smaller than 75
in thread 2
start: 4, end: 5
Thread 3: 73 is smaller than 75
Thread 4: 68 is smaller than 75
Thread 4: 4 is smaller than 75
Thread 4: 16 is smaller than 75
Thread 4: 15 is smaller than 75
--- Thread 4 created successfully ---
start: 6, end: 10
Thread 4: 68 is smaller than 73
Thread 4: 4 is smaller than 73
Thread 4: 16 is smaller than 73
Thread 4: 15 is smaller than 73
Thread 4: 4 is smaller than 68
Thread 4: 16 is smaller than 68
Thread 4: 15 is smaller than 68
Thread 4: 15 is smaller than 16
Thread 4: 15 is smaller than 94
in thread 4
Thread 4: 4 is smaller than 68
Thread 4: 16 is smaller than 68
Thread 4: 15 is smaller than 68
Thread 4: 15 is smaller than 16
Thread 4: 15 is smaller than 94
----- Sorting completed -----
我在这里看到的一个问题是,引用局部变量的地址。
struct PartitionBounds bounds;
int status = pthread_create(&sorters[i], NULL, sort, &bounds);
bounds
是局部变量,它将消失,每次迭代都会创建新实例。因此在 sort
函数中引用它会有 未定义的行为 .
你可以做的是,动态分配内存。
struct PartionBounds *bounds = malloc(sizeof(*bounds));
int status = pthread_create(&sorters[i], NULL, sort, bounds);
确保你free
记忆完成后。
不使用 malloc/free
的替代解决方案。
struct PartitionBounds bounds[HM_SORTERS];
...
size_t coverage = SIZE / HM_SORTERS;
bounds[i].tid = i;
bounds[i].start = i * coverage;
bounds[i].end = i + 1 == HM_SORTERS ? SIZE - 1 : bounds[i].start + coverage - 1;
int status = pthread_create(&sorters[i], NULL, sort, &bounds[i]);
...
我正在尝试用 C 编写一个多线程程序,通过将数组分成多个分区来对数组进行排序,然后每个线程在它自己的分区上工作。问题似乎是有时会跳过线程 1,有时会跳过线程 2。我什至没有进行排序,只是进行比较。现在我只想知道我的线程 运行 是否正确,但似乎第一个线程无法安排或其他什么。我对 C 不是很擅长,并且真的在绞尽脑汁想出什么问题。
我知道调度程序可以暂停每个线程,但它们最终都应该完成,对吧?那么为什么我的前几个线程有时不是 运行?
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <time.h>
#define SIZE 11
#define HM_SORTERS 4
void * sort(void * param);
void printArr(int * arr);
struct PartitionBounds {
int tid;
size_t start;
size_t end;
};
int array[SIZE] = {18, 12, 68, 59, 75, 73, 68, 4, 16, 94, 15};
int main() {
// srand(time(NULL));
// for (size_t i = 0; i < SIZE; i++) {
// array[i] = rand() % 100;
// }
printArr(array);
pthread_t sorters[HM_SORTERS];
for(int i=0;i<HM_SORTERS;i++) {
struct PartitionBounds bounds;
size_t coverage = SIZE / HM_SORTERS;
bounds.tid = i;
bounds.start = i * coverage;
bounds.end = i + 1 == HM_SORTERS ? SIZE - 1 : bounds.start + coverage - 1;
int status = pthread_create(&sorters[i], NULL, sort, &bounds);
if(status == 0) {
printf("\n--- Thread %d created successfully ---\n", i + 1);
printf("start: %zu, end: %zu\n", bounds.start, bounds.end);
} else {
printf("!!! Failed to create thread !!!\n");
return 0;
}
}
for(int i=0;i<HM_SORTERS;i++) {
pthread_join(sorters[i], NULL);
}
printf("\n\n----- Sorting completed -----\n\n");
return 0;
}
void * sort(void * param) {
struct PartitionBounds *bounds = param;
printf("\n\tin thread %d\n\n", bounds->tid + 1);
for(size_t i=bounds->start;i<=bounds->end;i++) {
for(size_t j=i+1;j<=bounds->end;j++) {
if(array[j] < array[i]) {
printf("Thread %d: %d is smaller than %d\n", bounds->tid + 1, array[j], array[i]);
}
}
}
pthread_exit(NULL);
}
void printArr(int * arr) {
int coverage = SIZE / HM_SORTERS;
for(int i=0;i<HM_SORTERS;i++) {
size_t partitionEnd = i + 1 == HM_SORTERS ? coverage + SIZE % HM_SORTERS : coverage;
for(int j=0;j<partitionEnd;j++) {
printf("%d", array[j + coverage * i]);
if(j+1 < partitionEnd) {
printf(", ");
}
}
if(i+1 < HM_SORTERS) {
printf(" | ");
}
}
printf("\n");
}
输出:(典型,当线程被跳过时)
18, 12 | 68, 59 | 75, 73 | 68, 4, 16, 94, 15
--- Thread 1 created successfully ---
start: 0, end: 1
--- Thread 2 created successfully ---
start: 2, end: 3
in thread 1
--- Thread 3 created successfully ---
Thread 3: 73 is smaller than 75
in thread 3
Thread 3: 73 is smaller than 75
in thread 2
start: 4, end: 5
Thread 3: 73 is smaller than 75
Thread 4: 68 is smaller than 75
Thread 4: 4 is smaller than 75
Thread 4: 16 is smaller than 75
Thread 4: 15 is smaller than 75
--- Thread 4 created successfully ---
start: 6, end: 10
Thread 4: 68 is smaller than 73
Thread 4: 4 is smaller than 73
Thread 4: 16 is smaller than 73
Thread 4: 15 is smaller than 73
Thread 4: 4 is smaller than 68
Thread 4: 16 is smaller than 68
Thread 4: 15 is smaller than 68
Thread 4: 15 is smaller than 16
Thread 4: 15 is smaller than 94
in thread 4
Thread 4: 4 is smaller than 68
Thread 4: 16 is smaller than 68
Thread 4: 15 is smaller than 68
Thread 4: 15 is smaller than 16
Thread 4: 15 is smaller than 94
----- Sorting completed -----
我在这里看到的一个问题是,引用局部变量的地址。
struct PartitionBounds bounds;
int status = pthread_create(&sorters[i], NULL, sort, &bounds);
bounds
是局部变量,它将消失,每次迭代都会创建新实例。因此在 sort
函数中引用它会有 未定义的行为 .
你可以做的是,动态分配内存。
struct PartionBounds *bounds = malloc(sizeof(*bounds));
int status = pthread_create(&sorters[i], NULL, sort, bounds);
确保你free
记忆完成后。
不使用 malloc/free
的替代解决方案。
struct PartitionBounds bounds[HM_SORTERS];
...
size_t coverage = SIZE / HM_SORTERS;
bounds[i].tid = i;
bounds[i].start = i * coverage;
bounds[i].end = i + 1 == HM_SORTERS ? SIZE - 1 : bounds[i].start + coverage - 1;
int status = pthread_create(&sorters[i], NULL, sort, &bounds[i]);
...