C++ C++  ·  25 вопросов  ·  ~70 мин  ·  ⏱ Таймер 10:00  ·  Средний  ·  👥 2 прошли

Многопоточность

Тест разбирает жизненный цикл потока, защиту общих данных, ожидание условий и взаимные блокировки. Вопросы не сводятся к названиям примитивов: нужно увидеть гонку, выбрать область блокировки и объяснить, почему код иногда зависает лишь под нагрузкой.

Отвечено: 0 из 25
⏱ --:--
0%
💡 Инструкция: Выберите один ответ из пяти. В тесте 25 вопросов, время — 70 минут. Во многих заданиях недостаточно узнать конструкцию: проследите порядок вычислений, время жизни объектов, владение ресурсами и условия, при которых решение остаётся корректным. После завершения откроются правильные ответы, объяснения, общий результат и тематические шкалы.
Вопрос 1 из 25
Что произойдёт, если уничтожить joinable std::thread?
C++C++20
void start_worker() {
    std::thread worker([] { process_queue(); });
    // выход из функции: worker всё ещё joinable
}
Вопрос 2 из 25
Чем join отличается от detach?
C++C++20
std::thread worker(run);
if (wait_for_result) {
    worker.join();
} else {
    worker.detach();
}
Вопрос 3 из 25
Почему передача `std::ref(x)` нужна, если функция потока принимает int&?
C++C++20
void increment(int& value) { ++value; }

int counter = 0;
std::thread worker(increment, std::ref(counter));
worker.join();
std::cout << counter;
Вопрос 4 из 25
Что происходит с исключением, вышедшим из функции потока?
C++C++20
std::thread worker([] {
    load_config();          // может бросить
    serve_requests();
});
worker.join();
Вопрос 5 из 25
Какое преимущество std::jthread?
C++C++20
void worker(std::stop_token stop) {
    while (!stop.stop_requested()) {
        process_one();
    }
}
std::jthread thread(worker);
Вопрос 6 из 25
Почему `counter++` из двух потоков без синхронизации является гонкой данных?
C++C++20
int counter = 0;

auto work = [&] {
    for (int i = 0; i < 100'000; ++i)
        ++counter;
};

std::thread a(work), b(work);
a.join(); b.join();
Вопрос 7 из 25
Что делает `std::lock_guard lock(m);`?
C++C++20
std::mutex mutex;
std::vector<int> queue;

void push(int value) {
    std::lock_guard lock(mutex);
    queue.push_back(value);
}
Вопрос 8 из 25
Почему критическую секцию стоит делать как можно короче, но не короче инварианта?
C++C++20
std::scoped_lock lock(account.mutex);
account.balance -= amount;
account.history.push_back(Transaction{amount});
account.version++;
// все три изменения образуют один инвариант
Вопрос 9 из 25
Как безопасно заблокировать два mutex без фиксированного ручного порядка?
C++C++20
std::mutex left;
std::mutex right;

void transfer() {
    std::scoped_lock lock(left, right);
    move_items();
}
Вопрос 10 из 25
Почему отдельные mutex для balance и transaction_count могут быть недостаточны?
C++C++20
std::mutex balance_mutex;
std::mutex count_mutex;
int balance;
int transaction_count;
// читатель должен видеть согласованную пару значений
Вопрос 11 из 25
Почему wait вызывают в цикле или с предикатом?
C++C++20
std::unique_lock lock(mutex);
ready_cv.wait(lock, [&] {
    return stopped || !queue.empty();
});
Вопрос 12 из 25
Почему `std::condition_variable::wait` принимает unique_lock, а не lock_guard?
C++C++20
std::mutex mutex;
std::condition_variable ready;
bool done = false;

std::unique_lock lock(mutex);
ready.wait(lock, [&] { return done; });
Вопрос 13 из 25
Что не так с ожиданием только уведомления без флага/очереди состояния?
C++C++20
// Поток A
{
    std::lock_guard lock(mutex);
    ready = true;
}
cv.notify_one();

// Поток B запускается позже
std::unique_lock lock(mutex);
cv.wait(lock);
Вопрос 14 из 25
Нужно ли держать mutex во время notify_one?
Вопрос 15 из 25
Какой шаблон корректен для потребителя очереди?
Вопрос 16 из 25
Как возникает классический deadlock с двумя mutex?
Вопрос 17 из 25
Какое простое правило снижает риск deadlock?
Вопрос 18 из 25
Почему опасно вызывать пользовательский callback под внутренним mutex?
Вопрос 19 из 25
Решает ли recursive_mutex проблему архитектуры с повторным входом?
Вопрос 20 из 25
Какой риск у вызова `future.get()` под mutex, если задача может потребовать тот же mutex?
C++C++20
std::mutex mutex;
std::future<int> result;

{
    std::lock_guard lock(mutex);
    result = std::async([&] {
        std::lock_guard inner(mutex);
        return calculate();
    });
    std::cout << result.get();
}
Вопрос 21 из 25
Что обнаруживает ThreadSanitizer?
Вопрос 22 из 25
Как сделать тест потерянного обновления более воспроизводимым?
Вопрос 23 из 25
Как проверить корректное завершение очереди работников?
Вопрос 24 из 25
Почему тест, прошедший тысячу раз, не доказывает отсутствия гонки?
Вопрос 25 из 25
Как локализовать редкий deadlock?

Ответьте на все 25 вопросов, чтобы получить результат

🔗 Встроить тест на свой сайт (iframe) ▼

Скопируйте код и вставьте в любое место на вашем сайте:

Также доступна прямая ссылка на embed-страницу