Оба потока выполнят по десять итераций, но фрагменты вывода могут перемешиваться. Кроме того, uint8_t часто является unsigned char, поэтому i выводится как символ, а не как число.
Отображение идентификаторов и счётчиков из разных потоков
Оба потока выполнят по десять итераций, но фрагменты вывода могут перемешиваться. Кроме того, uint8_t часто является unsigned char, поэтому i выводится как символ, а не как число.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Опишите и разберите поведение следующей программы, использующей стандартную библиотеку C++ для создания и управления потоками.
void worker() {
constexpr uint8_t SIZE = 10u;
for (uint8_t i = 0u; i < SIZE; ++i) {
std::cout << std::this_thread::get_id() << " => " << i << std::endl;
}
}
int main(int argc, char** argv) {
std::thread t1(worker);
std::thread t2(worker);
if (t1.joinable()) {
t1.join();
}
if (t2.joinable()) {
t2.join();
}
return EXIT_SUCCESS;
}
В ответе объясните, как происходит вывод из двух одновременно работающих потоков, почему используется joinable() и join(), а также какое влияние может оказывать планировщик потоков на порядок печати.
Ответ
Оба потока выполнят по десять итераций, но фрагменты вывода могут перемешиваться. Кроме того, uint8_t часто является unsigned char, поэтому i выводится как символ, а не как число.
Для числа используйте static_cast<unsigned>(i). Отдельная цепочка операций << не гарантирует атомарность строки: для цельного сообщения нужна общая блокировка либо std::osyncstream в C++20.
joinable проверяет, связан ли объект thread с потоком, который ещё не был join или detach; это не проверка «поток прямо сейчас работает». join ожидает завершения. Ожидание t1 прежде t2 не задаёт порядок их работы, поскольку оба потока уже запущены.