C Pthread: запуск только 10 потоков одновременно (в чем здесь проблема) - PullRequest
0 голосов
/ 27 сентября 2018

Так что я очень новичок во всей концепции pthread в C, но, пожалуйста, выслушайте меня.У меня есть следующий код:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <unistd.h>


static pthread_mutex_t  mutex = PTHREAD_MUTEX_INITIALIZER;

static pthread_cond_t   endCond = PTHREAD_COND_INITIALIZER;
static pthread_cond_t   startCond = PTHREAD_COND_INITIALIZER;

void * threadThingy(void * n){
    pthread_cond_wait(&startCond, &mutex);
    printf("%d: RAND: %d\n", *((int*)n), rand());

    //Lock mutex before broadcasting to main thread
    pthread_mutex_lock(&mutex);
    pthread_cond_broadcast(&endCond);
    pthread_mutex_unlock(&mutex);


    free(n);
    fflush(stdout);
    return 0;
}


int main(void){
    printf("Starting\n");
    pthread_t threads[100];
    int i = 0;

    while(i < 10){
        int *arg = malloc(sizeof(int));
        *arg = i;
        pthread_create(&threads[i], NULL, threadThingy, arg);
        i++;
    }

    pthread_mutex_lock(&mutex);
    pthread_cond_broadcast(&startCond);

    int finished = 0;

    while(finished <= 100){
        pthread_cond_wait(&endCond, &mutex);

        //Lock mutex so no other requests can come in
        pthread_mutex_lock(&mutex);
        finished++;

        int *arg = malloc(sizeof(int));
        *arg = 11;
        pthread_create(threads[i], NULL, threadThingy, arg);
        i++;
        pthread_cond_broadcast(&startCond);
        pthread_mutex_unlock(&mutex);

    }

    printf("Stopping\n");

    sleep(1000);
}

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

Начиная с 0: RAND: 1804289383

Ответы [ 2 ]

0 голосов
/ 28 сентября 2018

Как упомянуто Lavigne958, в функции threadThingy () существует тупик, вызванный pthread_cond_wait (), поскольку он получит блокировку.Опять же, вы пытаетесь заблокировать его в следующей строке.Это вызывает тупик.

Необходимо проверить несколько вещей:

  1. Вам необходимо заблокировать мьютекс перед вызовом pthread_cond_wait ().

  2. Если вы решите вышеуказанную проблему, использование нескольких условных переменных с одним и тем же мьютексом может вызвать дальнейшую тупиковую ситуацию.

  3. Если вы не присоединяетесь к потокам, будет лучшедля создания отдельных потоков с использованием атрибута PTHREAD_CREATE_DETACHED.

  4. Проблема N количества одновременно работающих потоков может быть решена с помощью одного семафора ИЛИ одной переменной условия (и одного мьютекса).Пример с семафором приведен ниже.

    #include <stdio.h>
    #include <pthread.h>
    #include <semaphore.h>
    #include <unistd.h>
    
    sem_t mysem;
    #define NUM_CONCURRENT_THREADS 4
    #define MAX_THREADS 40
    
    void *thread(void *arg)
    {
            printf("Thread id %ld: started\n", pthread_self());
            sleep(5); // Do some work
            printf("Thread id %ld: Exiting\n", pthread_self());
            sem_post(&mysem);
            return NULL;
    }
    
    
    int main()
    {
            pthread_t t[MAX_THREADS];
            pthread_attr_t attr;
            int rc, i = 0;
    
            sem_init(&mysem, 0, NUM_CONCURRENT_THREADS);
            rc = pthread_attr_init(&attr);
            rc = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    
            printf("\nParent begin\n");
            while(i < MAX_THREADS)
            {
                    sem_wait(&mysem);
                    pthread_create(&t[i], &attr, thread, NULL);
                    i++;
            }
            printf("\nParent end.\n");
    
            sem_destroy(&mysem);
            return 0;
    }
    

Пожалуйста, проверьте блог Tech Easy для получения дополнительной информации о темах.

0 голосов
/ 27 сентября 2018

в функции, которую запускают ваши потоки, вы начинаете с ожидания условия, но вы забыли использовать мьютекс раньше.Таким образом, сначала вы должны взять мьютекс, прежде чем ждать условия.

у вас есть то, что мы называем тупиком.

Что происходит:

  1. первый поток пробуждаетсявверх (функция pthread_con_wait уже получает блокировку для вас)
  2. затем вы пытаетесь снова получить блокировку => взаимоблокировка, потому что у вас уже есть блокировка, поэтому вы сами как бы блокируете ее.
...