2014-11-28 3 views
2

Я не знаю, связана ли эта тема с библиотекой std :: thread или потоками. Посмотрите на следующий пример:Странное поведение библиотеки потоков

#include <thread> 
#include <iostream> 

void read(){ 
    int bar; 
    std::cout << "Enter an int: "; 
    std::cin >> bar; 
} 

void print(){ 
    std::cout << "foo"; 
} 

int main(){ 
    std::thread rT(read); 
    std::thread pT(print); 
    rT.join(); 
    pT.join(); 
    return 0; 
} 

Я не волнует, если он напечатает «Foo» строку до или после выполнения функции чтения(). Меня беспокоит тот факт, что когда он запрашивает ввод перед выполнением функции print(), он фактически зависает. Мне нужно нажать «ввести» или передать std :: cin с некоторыми данными, чтобы увидеть строку «foo». Ниже вы можете видеть три возможных сценария того, как эта программа ведет себя:

1. 
>> Enter an int: //here I've clicked enter 
>> foo 
>> 12 //here I've written "12" and clicked enter 
//end of execution 

2. 
>> fooEnter an int: 12 //here I've written "12" and clicked enter 
//end of execution 

3. 
>> Enter an int: 12 //here I've written "12" and clicked enter 
>> foo 
//end of execution 

Как вы можете видеть, иногда я должен нажать войти, чтобы увидеть «Foo» строку. По-моему, он должен печататься каждый раз, так как он был запущен в отдельном потоке. Может быть, std :: cin каким-то образом блокирует std :: cout? Если да, то что мне делать?

ответ

7

Это нормально, выход по умолчанию std::cout. cout привязан к cin, поэтому, когда вы начинаете читать с cin или нажмите Enter, буфер cout будет покраснел и появится на экране.

Возможно, что первый поток записывает свой вывод, который буферизуется, а затем ожидает ввода, который очищает выходной буфер (так что вы видите "Enter an int:"), тогда второй поток записывает свой вывод, но он находится в буфере пока вход не будет прочитан, когда выход снова будет сброшен.

Вы можете заставить вторую нить к выходу сразу промывкой его буфер вручную:

std::cout << "foo" << std::flush; 

Это, вероятно, приведет либо "fooEnter an int:" или "Enter an int:foo", но вам не нужно нажимать Enter, прежде чем "foo" появится.

+2

'std :: endl' является альтернативой, так как это в основном' \ n '+ std :: flush' – MSalters