не понимаю результат работы параллельной программы

есть такой импровизированный участок кода

#include <iostream>
#include <vector>
#include <algorithm>
#include <thread>

void print_string(const std::string message)
{
  std::cout << message;
}

int main()
{
  std::thread t1(print_string, "hello ");
  t1.detach();
  std::vector<int> nums(2000);
  for (int i = 0;i < nums.size();++i) {
    nums[i] = rand();
  }
  sort(nums.begin(), nums.end());
  std::cout << "world!\n";
  return 0;
}

результаты работы: 1) hello world! -- такой исход мне понятен

не понятны такие исходы: 2) world! 3) world! hello

то есть здесь 2000 элементов инициализировались и отсортировались и еще произошел вывод "world!" быстрее чем вывело "hello "? почему такое происходит?


Ответы (1 шт):

Автор решения: AlexGlebe

Есть такое понятие, как буфер потока. Пока вы не сделаете cout.flush(); строку 'hello ' - не увидите.

Стандарт :

Concurrent access to a stream object (27.8, 27.9), stream buffer object (27.6), or C Library stream (27.9.2) by multiple threads may result in a data race (1.10) unless otherwise specified (27.4). [ Note: Data races result in undefined behavior (1.10). — end note ]

Concurrent access to a synchronized (27.5.3.4) standard iostream object’s formatted and unformatted input (27.7.2.1) and output (27.7.3.1) functions or a standard C stream by multiple threads shall not result in a data race (1.10). [ Note: Users must still synchronize concurrent use of these objects and streams by multiple threads if they wish to avoid interleaved characters. — end note ]

Перевод :

Одновременный доступ к объекту потока (27.8, 27.9), объекту буфера потока (27.6) или потоку библиотеки C (27.9.2) несколькими потоками может привести к гонке данных (1.10), если не указано иное (27.4). [Примечание: гонки данных приводят к неопределенному поведению (1.10). - конец примечания]

Одновременный доступ к синхронизированным (27.5.3.4) стандартным функциям входного (27.7.2.1) и выходного (27.7.3.1) ввода или вывода (27.7.3.1) стандартного объекта iostream или стандартному потоку C несколькими потоками не должен приводить к гонке данных (1.10). [Примечание: пользователи по-прежнему должны синхронизировать одновременное использование этих объектов и потоков несколькими потоками, если они хотят избежать чередования символов. - конец примечания]

Так работает чётко :

void print_string(const std::string message)
{
  std::cout << message;
  std::cout.flush();
}
→ Ссылка