2013-04-18 3 views
0

Я пытаюсь реализовать объект производителя/потребителя, когда поток производителя захватывает символы из строки и помещает их в очередь с круговым связанным списком (5 узлов большие) и потребительский поток считывает символы и выводит их на экран. Оба потока останавливаются, когда они достигают нового символа линии. Проблема, с которой я сталкиваюсь, заключается в том, что потребительский поток никогда не запускается до тех пор, пока продюсерский поток не завершится.Второй поток не запускается до тех пор, пока не будет завершен первый этап

int consumer_thread_alive; 
... 

void * producer(struct Node * head) 
{ 
    while (consumer_thread_alive == 0) 
    { 
     printf("Waiting on consumer."); 
    } 
... 
} 

void * consumer(struct Node * head) 
{ 
    consumer_thread_alive = 1; 
... 
} 
... 

int main(int argc, char *argv[]) 
{ 
    ... 
    consumer_thread_alive = 0; 
    pthread_t produce; 
    pthread_t consume; 
    printf("Creating producer thread.\n"); 
    pthread_create(&produce, NULL, (void *) producer(&head), NULL); 
    printf("Creating consumer thread.\n"); 
    pthread_create(&consume, NULL, (void *) consumer(&head), NULL); 
    pthread_join(produce,NULL); 
    pthread_join(consume,NULL); 
    return 1; 
} 

Я вырезал некоторые из других частей, но то, где у меня возникают проблемы (глава инициализируется ранее в основном). Если я запустил код, так как он печатает «Создание потока производителей». а затем постоянно печатает «Ожидание потребителя». пока я не нажму Ctrl + C и остановите его. Кроме того, если я удаляю цикл в верхней части потока производителя, он запускает все его итерации, а затем вызывается потребительский поток. По какой-то причине он работает последовательно, а не параллельно.

+2

Вы не можете синхронизировать потоки с простой переменной 'int'. Вы должны использовать правильные примитивы синхронизации. –

+3

Вызов 'pthread_create()' неправильный. – alk

+2

Не игнорируйте предупреждения своего компилятора и не просто пытайтесь убить предупреждения с помощью бросков. (Иногда приведение является правильным, но чаще всего это неправильное решение проблемы, которая диагностируется.) Помните, что компилятор знает больше о C, чем вы. –

ответ

6

Изменить

pthread_create(&produce, NULL, (void *) producer(&head), NULL); 

быть:

pthread_create(&produce, NULL, producer, &head); 

(то же самое для потребителя)


И: Вы должны всегда проверять результаты системных вызовов!


И^2: Защищайте одновременный доступ к consumer_thread_alive с помощью мьютекса, например!


И^3: Функция нить ougth иметь следующий вид:

void * thread_func(void *); 

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

void * producer(void * pvhead) 
{ 
    struct Node * head = pvhead; 
    ... 

Но быть в курсе , что по мере того, как вы находитесь , пройдите ссылку на те же экземпляр struct Nodeкак к нитей, поэтому одновременное доступ к нему внутри резьбы функций должна быть защищена, а также (см И^2 выше).

+1

+1 Хорошая работа ... –

+0

+1 для тщательного и тщательного объяснения всех проблем, возникающих с помощью этого кода. Yay для многопоточности! –

+0

@JonathanLeffler: Спасибо ... :-) – alk

1
int pthread_create(pthread_t *restrict thread, const pthread_attr_t *restrict attr, 
      void *(*start_routine)(void*), void *restrict arg); 

выше синтаксис объявлен для pthread_create в #include <pthread.h> заголовочном файле.

так что вы должны изменить следующие работы

pthread_create(&produce, NULL, producer, (void *)&head); 

ПОЛНЫЙ КОД РАБОЧИЙ:

#include <stdio.h> 
#include <stdlib.h> 
#include <pthread.h> 
void * producer(void *); 
void * consumer(void *); 
struct node{ 
int x; 
}; 
struct node head; 
int consumer_thread_alive; 
void * producer(void * head) 
{ 
    printf("producer\n"); 
    pthread_exit(NULL);  
} 
void * consumer(void * head) 
{ 
    consumer_thread_alive = 1; 
    printf("consumer\n"); 
    pthread_exit(NULL); 
} 

int main(int argc, char *argv[]) 
{ 
    consumer_thread_alive = 0; 
    pthread_t produce; 
    pthread_t consume; 
    printf("Creating producer thread.\n"); 
    pthread_create(&produce, NULL, producer, (void*)&head); 
    printf("Creating consumer thread.\n"); 
    pthread_create(&consume, NULL, consumer, (void*)&head); 
    pthread_join(produce,NULL); 
    pthread_join(consume,NULL); 
    return 1; 
} 
0
pthread_create(//producer's) 
pthread_join(//producer's) 
pthread_create(//consumer's) 
pthread_join(//consumer's) 

этот порядок будет работать.

EDIT: Это сработало, когда я попытался реализовать одно и то же. Просто попробуй.

+0

Нет; это неразумно. Производитель не выйдет до тех пор, пока потребитель не будет запущен, поэтому первое соединение не будет работать. –