#c #arrays #multithreading #posix #semaphore
#c #массивы #многопоточность #posix #семафор
Вопрос:
В настоящее время я пишу программу, которая принимает массив, содержащий случайно сгенерированные числа, и использует многопоточность, чтобы по существу разделить массив на равные части, тогда каждый поток найдет минимум соответствующего разделения массива. По сути, мне нужно, чтобы мой родительский поток был заблокирован (был незанят в ожидании эффективности параллельной обработки) с использованием семафоров, в то время как дочерние потоки ищут минимум, однако комбинация 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 Sizen");
exit(-1);
}
gThreadCount = atoi(argv[2]);
if(gThreadCount > MAX_THREADS || gThreadCount <=0){
fprintf(stderr, "Invalid Thread Countn");
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(amp;mutex, 0, 1);
sem_init(amp;completed, 0, 0);
for(i=0; i < gThreadCount; i ){
pthread_attr_init(amp;attr[i]);
pthread_create(amp;tid[i],amp;attr[i],ThFindMinWithSemaphore,amp;indices[i]);
}
sem_wait(amp;completed);
if(gThreadDone[i] == true amp;amp; 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 = %dn", 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(amp;completed);
for (i = startIndex; i < endIndex; i ) {
if (gData[i] < gThreadMin[threadNum]){
gThreadMin[threadNum] = gData[i];
}
else if (gData[i] == 0){
sem_post(amp;completed);
pthread_exit(0);
}
}
sem_wait(amp;mutex);
gDoneThreadCount ;
sem_post(amp;mutex);
if (gDoneThreadCount == gThreadCount){
sem_post(amp;completed);
}
pthread_exit(0);
}
Обратите внимание, что это не весь код файла, который на самом деле находится в файле.
Я хочу, чтобы основная функция ожидала в строке, где написано sem_wait (amp;завершено). Цель состоит в том, чтобы дочерние потоки сигнализировали родительскому с помощью sem_post, когда каждый поток завершает поиск своего минимального значения, или один из потоков нашел ноль в массиве. Тогда в этот момент основная функция должна продолжиться после получения этого сигнала sem_post.
Как я понимаю, если семафор завершен, имеет нулевое значение, которое я инициализировал с помощью sem_init(amp;завершено, 0, 0), вызывающий sem_wait ожидает, пока не получит sem_post от одного из дочерних потоков. Похоже, что моя программа не выполняет ожидание, как ожидалось.
Комментарии:
1. Это не ответ, но… Мьютекс не является семафором. Вы должны использовать pthread_mutex для мьютекса.
2. Можете ли вы сказать, какое поведение вы наблюдаете? Для меня это выглядит как взаимоблокировка, поскольку «завершено» имеет начальное значение «0», и вы выполняете «sem_wait(amp;completed);» как в main (), так и в ThFindMinWithSemaphore(). Итак, «sem_wait(amp;completed);» в ThFindMinWithSemaphore() следует удалить.