В настоящее время я пишу программу, которая берет массив, который имеет случайно сгенерированные числа, и использует многопоточность, чтобы по существу разделить массив на равные части, тогда каждый поток найдет минимум своего соответствующего деления массива.По сути, мне нужно, чтобы мой родительский поток был заблокирован (не занят в ожидании эффективности параллельной обработки) с использованием семафоров, в то время как дочерние потоки ищут минимум, однако комбинация sem_wait и sem_post не блокирует родительский поток, как ожидалось.
Я пытался изменить параметры sem_init на другие значения, однако, кажется, что независимо от того, что я делаю, родительский объект на самом деле не блокируется.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/timeb.h>
#include <semaphore.h>
#include <stdbool.h>
#include <unistd.h>
#define MAX_SIZE 100000000
#define MAX_THREADS 16
#define RANDOM_SEED 8631
#define MAX_RANDOM_NUMBER 5000
// Global variables
long gRefTime; //For timing
int gData[MAX_SIZE]; //The array that will hold the data
int gThreadCount; //Number of threads
int gDoneThreadCount; //Number of threads that are done at a certain point. Whenever a thread is done, it increments this. Used with the semaphore-based solution
int gThreadMin[MAX_THREADS]; //The minimum value found by each thread
bool gThreadDone[MAX_THREADS]; //Is this thread done? Used when the parent is continually checking on child threads
int indices[MAX_THREADS][3];
// Semaphores
sem_t completed; //To notify parent that all threads have completed or one of them found a zero
sem_t mutex; //Binary semaphore to protect the shared variable gDoneThreadCount
int main(int argc, char *argv[]){
pthread_t tid[MAX_THREADS];
pthread_attr_t attr[MAX_THREADS];
int i, indexForZero, arraySize, min;
// Code for parsing and checking command-line arguments
if(argc != 4){
fprintf(stderr, "Invalid number of arguments!\n");
exit(-1);
}
if((arraySize = atoi(argv[1])) <= 0 || arraySize > MAX_SIZE){
fprintf(stderr, "Invalid Array Size\n");
exit(-1);
}
gThreadCount = atoi(argv[2]);
if(gThreadCount > MAX_THREADS || gThreadCount <=0){
fprintf(stderr, "Invalid Thread Count\n");
exit(-1);
}
indexForZero = atoi(argv[3]);
if(indexForZero < -1 || indexForZero >= arraySize){
fprintf(stderr, "Invalid index for zero!\n");
exit(-1);
}
GenerateInput(arraySize, indexForZero);
CalculateIndices(arraySize, gThreadCount, indices);
InitSharedVars();
SetTime();
// Initialize threads, create threads, and then make the parent wait on the "completed" semaphore
// The thread start function is ThFindMinWithSemaphore
sem_init(&mutex, 0, 1);
sem_init(&completed, 0, 0);
for(i=0; i < gThreadCount; i++){
pthread_attr_init(&attr[i]);
pthread_create(&tid[i],&attr[i],ThFindMinWithSemaphore,&indices[i]);
}
sem_wait(&completed);
if(gThreadDone[i] == true && gThreadMin[i] == min){
for(i=0; i < gThreadCount; i++){
pthread_cancel(tid[i]);
}
}
min = SearchThreadMin();
printf("Threaded FindMin with parent waiting on a semaphore completed in %ld ms. Min = %d\n", GetTime(), min);
void* ThFindMinWithSemaphore(void *param) {
int threadNum = ((int*)param)[0];
int i;
int startIndex = indices[threadNum][1];
int endIndex = indices[threadNum][2];
sem_wait(&completed);
for (i = startIndex; i < endIndex; i++) {
if (gData[i] < gThreadMin[threadNum]){
gThreadMin[threadNum] = gData[i];
}
else if (gData[i] == 0){
sem_post(&completed);
pthread_exit(0);
}
}
sem_wait(&mutex);
gDoneThreadCount++;
sem_post(&mutex);
if (gDoneThreadCount == gThreadCount){
sem_post(&completed);
}
pthread_exit(0);
}
Обратите внимание, что это не всекода файла, который на самом деле находится в файле.
Я хочу, чтобы основная функция ждала в строке, где написано sem_wait (& complete).Цель состоит в том, чтобы дочерние потоки сигнализировали родителю с помощью sem_post, когда каждый поток завершил поиск своего минимального значения или один из потоков нашел ноль в массиве.Затем в этот момент основная функция должна продолжиться после получения этого сигнала sem_post.
Как я понимаю, если завершенный семафор имеет счетчик нуля, который я инициализировал для него с помощью sem_init (& done, 0, 0)вызывающий sem_wait ждет, пока не получит sem_post от одного из дочерних потоков.Похоже, что моя программа не выполняет ожидание, как ожидалось.