Как я могу установить конец потока только тогда, когда другие потоки работают? - PullRequest
0 голосов
/ 04 мая 2020

Я создал 44 потока, в которых одновременно работают только 6 потоков, и я хочу, чтобы поток 13 заканчивался только тогда, когда значение семафора равно 0 (запущены еще 5 потоков). Я пробовал с условной переменной что-то вроде этого:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <fcntl.h>
int curr_threads = 0;
int sem_id;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t end13 = PTHREAD_COND_INITIALIZER;

void P(int sem_id){
    struct sembuf semaphore_op = {0, -1, 0};
    semop(sem_id, &semaphore_op, 1);    
}

void V(int sem_id){
    struct sembuf semaphore_op = {0, 1, 0};
    semop(sem_id, &semaphore_op, 1);    
}

void* thread_func(void* arg) {
    P(sem_id);
    pthread_mutex_lock(&mutex);
    curr_threads++;
    if(curr_threads == 6) pthread_cond_signal(&end13);
    pthread_mutex_unlock(&mutex);
    int* thread_nr = (int*) arg;
    if(*thread_nr == 13) {
        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&end13, &mutex);
        pthread_mutex_unlock(&mutex); 
    }
    pthread_mutex_lock(&mutex);
    curr_threads--;
    pthread_mutex_unlock(&mutex);
    V(sem_id);
    return (void*) 0;
}
int main(int argc, char** argv) {
    sem_id = semget(1234, 1, IPC_CREAT | 0600);
    pthread_t threads[44];
    semctl(sem_id, 0, SETVAL, 6);
    int aux[44];
    for(int i = 0; i < 44; i++) {
        aux[i] = i + 1;
    }

    for(int i = 0; i < 44; i++) {
        pthread_create(&threads[i], NULL, thread_func, &aux[i]);
    }

    for(int i = 0; i < 44; i++) {
        pthread_join(threads[i], NULL);
    }        
    exit(0);
}

Но это не работает. Есть предложения?

1 Ответ

0 голосов
/ 04 мая 2020
if(*thread_nr == 13) {
    pthread_mutex_lock(&mutex);
    pthread_cond_wait(&end13, &mutex);
    pthread_mutex_unlock(&mutex); 
}

Переменные условия не имеют состояния и требуют использования соответствующего мьютекса для защиты состояния. Мьютекс здесь ничего не защищает, поэтому вы не ждете ничего. Вы никогда не получите переменную условия для правильной работы таким образом.

Скорее всего, ваш код завершится ошибкой, потому что этот поток вызывает pthread_cond_wait, даже когда ждать нечего, и поэтому он ждет вечно. Вы приобрели мьютекс для проверки общего состояния, но потом этого не сделали.

Вам нужно либо не использовать условные переменные, либо узнать, как они работают. В частности, вы должны понять, что в основном они обеспечивают атомную c операцию «разблокировки и ожидания», чтобы избежать состояния гонки, когда вы ожидаете чего-то, что уже произошло.

Чтение этот вопрос и ответы на него могут помочь.

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