c многопоточностью - PullRequest
       12

c многопоточностью

0 голосов
/ 24 апреля 2010

В моих темах странное поведение:

void * foo(void * nic){
    printf("foo");
}
void * threadF(void * pointer){
    printf("1\n");
    pthread_t threadT;
    pthread_attr_t attr;
    pthread_attr_init (&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
    pthread_create(&threadT,NULL,&foo,(void*)NULL);
    printf("2\n");
    while (!feof(stdin)){
        int id, in, out;
        fscanf(stdin,"%d:%d:%d",&id,&in,&out);
    }
}

int main(){
    pthread_attr_t attr;
    pthread_attr_init (&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
    pthread_t threadT;
    pthread_create(&vlaknoVstupu,&attr,&threadF,(void*)&data);
    pthread_join(threadT,NULL);
    pthread_attr_destroy (&attr);
}
// I skipped irelevant parts of code...

Дело в том, что иногда результат равен 12foo, но обычно просто 12. Затем функция ожидает ввода. Я ожидал бы, что это будет всегда 12foo. Кто-нибудь знает, почему мои ожидания неверны?

Редактировать: когда я набираю какой-либо ввод, например 1:1:1, что приводит к повторному прохождению цикла while, равен , всегда foo выход.

Ответы [ 3 ]

2 голосов
/ 24 апреля 2010

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

Что вам нужно сделать, это сохранить буфер строковых указателей и использовать атомарные операции для вставки строк в этот буфер, а затем время от времени выводить все из них printf, освобождать память, устанавливать значение null или просто использовать блокировку, если она хорошо, чтобы дочерние потоки ожидали вызова printf.

1 голос
/ 24 апреля 2010

Что происходит, так это то, что (в большинстве реализаций) stdin и stdout связаны в одном практическом буфере. Это позволяет что-то вроде:

printf("Input: ");
scanf("%d", &integer);

для правильной работы введенные символы появятся после текста printf.

Как только ваш scanf захватит stdin, это «заблокирует» этот буфер, также предотвратив вывод stdout вашего другого потока на экран. Обратите внимание, что «замок». Не обязательно означает реальные блокировки потоков.

Если вы вызываете программу из консоли, вводите что-то вроде 1: 2: 3 и нажимаете enter, вы увидите, что foo будет отображаться в конце.

0 голосов
/ 24 апреля 2010

Поскольку для потока foo нет вызова объединения, программа, вероятно, завершается до того, как запустится.

...