Я разбил свою проблему на что-то воспроизводимое. В следующем коде у нас есть класс printer
. printer::run
напечатает id_
этого printer
. printer::spawn
даст вам ветку с новым принтером.
В main
Я создаю 10 принтеров. Созданные темы будут объединены в конце main
. Я ожидал бы, что мы получим числа от 0 до 9 в некотором порядке каждый раз, когда мы запускаем это (это «детерминированное c поведение» из заголовка). Это не вариант. Иногда мы получаем другие цифры. Это почему?
#include <thread>
#include <iostream>
#include <vector>
class printer
{
public:
printer(int i) : i_(i){};
void run()
{
std::cout << i_ << '\n';
}
std::shared_ptr<std::thread> spawn()
{
return std::make_shared<std::thread>([=]() { run(); });
}
private:
int i_;
};
int main()
{
std::vector<std::shared_ptr<std::thread>> vec;
for (int i = 0; i < 10; ++i)
{
printer p{i};
vec.push_back(p.spawn());
}
for (auto a : vec)
{
a->join();
}
return 0;
}
Некоторые мысли о моем ожидании:
Я бы догадался, что мы копируем состояние текущего printer
при вызове spawn, потому что мы фиксируем состояние по значению (лямбда) не по ссылке.
Даже если мы будем захватывать по ссылке, мы все равно копируем состояние в новый поток.
И даже если этого не происходит, у каждого потока есть свой printer
. Что мне не хватает?
Некоторые примеры выходных данных:
(для краткости я положил все числа в одну строку)
1, 3, 4, 2, 5, 6, 7, 8, 9, -116618192
1513168144, 1513168144, 1513168144, 1513168144, 1513168144, 1513168144, 1513168144, 1513168144, 1513168144, 1513168144
1, 2, 33, , 6, 6, 7, 9, 9, 1344437296
1, 43, 2, 6, , 6, 7, 8, 9, -1194894256
Некоторые выходы не имеют всех 10 число ...