2016-02-17 2 views
0

Я написал очень простой код для практики семафора. Задача состоит в том, чтобы продавать билеты, и каждый поток должен обновлять общую переменную от общего количества билетов до тех пор, пока она не станет нулевой. Проблема, которую я наблюдаю, - это нить, которая продает последний билет и делает ticket_count = 0, уменьшая его выход, не печатая, сколько всего проданных билетов. Я добавил mutex вокруг printf только для его взлома, поскольку я читал о проблемах printf в многопоточной среде на SO. Причина. Я нахожу, что эта проблема отличается от обычных проблем с printf, указанных в SO в отношении многопоточности, - это всегда (не всегда 8/10 раз - проблема прерывистая), другая в 2 раза печатает все проданные 4 бита нитей, тот, который продает последний билет, пропускает printf и выходит. Может кто-нибудь указать мне, что я делаю неправильно?ошибка выхода потока в многопоточном сценарии

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

#define NUMTHREADS 4  /* number of threads i.e. ticket sellers */ 

static unsigned int ticket_count = 25; 

pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER; 

sem_t mutex; 

void *ticketProcessing(void *arg) 
{ 
    bool loop_alive = true; 
    int local_counter = 0; 
    while(loop_alive) 
    { 
     sleep(1); 
     sem_wait(&mutex); 
     if (ticket_count > 0) 
     { 
      local_counter++; 
      ticket_count--; 
      printf(" thread id -- %d - decided to sell 1 ticket \n ", (int)pthread_self()); 
     } 
     else 
     { 
      loop_alive = false; 
     } 
     sem_post(&mutex); 
    } 

    pthread_mutex_lock(&mutex2); 
    printf(" ticket sold by thread id -- %d -- is %d \n ", (int)pthread_self(), local_counter); 
    pthread_mutex_unlock(&mutex2); 
    // return 0; 
} 

int main(void) 
{ 
    pthread_t sellingTicket; 
    sem_init(&mutex, 0, 1); 
    int i; 

    for(i = 0; i < NUMTHREADS; i++) 
    { 
     pthread_create(&sellingTicket, NULL, ticketProcessing, NULL); 
    } 

    i = 0; 
    while(i < NUMTHREADS) 
    { 
     pthread_join(sellingTicket, NULL); 
     i++; 
    } 


    printf(" All threads exited !!! \n "); 
    return 0; 
} 

Edit: я попытался создать массив и присоединиться ниже моды, и она работает

pthread_t threads[4]; 

for(i = 0; i < 4; i++) 
{ 
    pthread_create(&threads[i], NULL, ticketProcessing, NULL); 
} 

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

Ошибка синхронизации основного вашего потока. Поэтому он не ждет должным образом всех потоков для выхода до выхода из основного потока (который также останавливает все дочерние потоки). 'pthread_join (sellingTicket, NULL)'. Это ожидает * тот же самый поток в каждом цикле - последний поток, который нужно создать. Для каждого дочернего потока вам понадобится * отдельная переменная 'sellingTicket' pthread_t *. – kaylum

+0

@kaylum - я вижу, что вы делаете, но не можете реализовать - pthread_join, чтобы он ловил весь созданный поток, не могли бы вы привести пример в моем сценарии? Как я создал темы – thedreamer

ответ

3

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

Как только вы присоединились к потоку, идентификатор потока недействителен, и это серьезная ошибка передать его любой функции pthread_ *.

+0

Извините, но я все еще не могу понять и, на удивление, я не нахожу пример, чтобы присоединиться к нескольким потокам, которые я создал. Не могли бы вы добавить это с ответом? Также цикл while, который я поддерживал около pthread_join, был во время дополнительной отладки. Если я удаляю цикл while рядом с pthread_join и просто сохраняю pthread_join (sellTicket, NULL); Я не вижу никакого влияния на результат – thedreamer

+0

'@thedreamer, если вы хотите присоединиться ко всем потокам, вы shoud make' sellingTicket 'массив. Просто посмотрите на свой код еще раз - цикл pthread_create() перезаписывает один и тот же «sellTicket» var каждый раз, поэтому теряя все ссылки на резьбу, кроме последнего :( –

+0

@MartinJames: Спасибо за указатель, да, я сделал это в конце концов как обновлено в разделе редактирования, и все работает нормально. Вопрос: почему я должен получить 4 разных идентификатора потока, если произошла перезапись и возвращение из 3 потоков (hmm ..atleast printf показал 3 разных идентификатора потока), а не только 1? вы, пожалуйста, помогите мне понять это. – thedreamer

Смежные вопросы