Возможна ли другая последовательность выполнения потоков кроме последовательного запуска?
Что проверяют
Понимаете ли вы, что порядок запуска потоков ничего не говорит о порядке их выполнения. Следом обычно просят показать, как заставить потоки работать в нужной очерёдности и что будет, если они без синхронизации пишут в общие данные.
Как отвечать
Да, возможна любая. Если создать подряд std::thread t1, t2, t3, ОС лишь ставит их в очередь планировщика. Кто стартует первым, на каком ядре и когда будет вытеснен, решает планировщик, поэтому вывод трёх потоков может перемешаться даже внутри одной строки: std::cout защищён от гонки на своих данных, но цепочку << в одну операцию не склеивает. Для этого в C++20 есть std::osyncstream.
Порядок на уровне памяти тоже не гарантирован: компилятор и процессор переставляют операции, и без синхронизации другой поток может увидеть записи в ином порядке. Одновременная запись в общую переменную без синхронизации это data race, то есть неопределённое поведение.
Чем задают порядок:
join(): дождаться завершения потока.std::jthreadиз C++20 делаетjoinв деструкторе;std::mutexиstd::condition_variable: один поток ждёт условия, другой выставляет его и будит. Ждать нужно с предикатом из-за ложных пробуждений;std::promiseиstd::future: передать результат или сигнал готовности;std::latchиstd::barrier(C++20): дождаться, пока соберутся N потоков;std::atomicсmemory_order_releaseиmemory_order_acquire: всё записанное до release видно после acquire.
Отдельно про std::async: с политикой по умолчанию реализация вправе выполнить задачу отложенно, в вызывающем потоке при get(). Если нужна параллельность, указывайте std::launch::async.
Где спотыкаются
Проверяют порядок запуском на своей машине: «десять раз шло по порядку». Это совпадение, под нагрузкой или на другом числе ядер картина будет другой.
Ставят sleep_for для «упорядочивания». Задержка ничего не гарантирует и лишь прячет гонку до первого загруженного сервера.
Считают volatile средством синхронизации. В C++ он не даёт ни атомарности, ни упорядочивания между потоками, для этого есть std::atomic.