Почему моя блокировка семафора не блокирует этот процесс, как ожидалось? (Многопоточность) - PullRequest
0 голосов
/ 02 апреля 2019

В настоящее время я пишу программу, которая берет массив, который имеет случайно сгенерированные числа, и использует многопоточность, чтобы по существу разделить массив на равные части, тогда каждый поток найдет минимум своего соответствующего деления массива.По сути, мне нужно, чтобы мой родительский поток был заблокирован (не занят в ожидании эффективности параллельной обработки) с использованием семафоров, в то время как дочерние потоки ищут минимум, однако комбинация 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 от одного из дочерних потоков.Похоже, что моя программа не выполняет ожидание, как ожидалось.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...