Что выведет код Middle Многопоточность и модель памяти обновлено
Что выведет: атомик, мьютекс и CAS
Вопрос
Что выведет программа (C++20, g++ 14)? Каждый вывод с новой строки, как в консоли.
#include <atomic>
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
int main() {
std::atomic<int> counter{0};
int plain = 0;
std::mutex m;
std::vector<std::thread> ts;
for (int i = 0; i < 4; ++i)
ts.emplace_back([&] {
for (int j = 0; j < 1000; ++j) {
counter.fetch_add(1, std::memory_order_relaxed);
std::lock_guard lock(m);
++plain;
}
});
for (auto& t : ts) t.join();
std::cout << counter.load() << ' ' << plain << '\n';
std::atomic<int> x{5};
int expected = 5;
bool ok = x.compare_exchange_strong(expected, 7);
std::cout << ok << ' ' << x.load() << ' ' << expected << '\n';
ok = x.compare_exchange_strong(expected, 9);
std::cout << ok << ' ' << x.load() << ' ' << expected << '\n';
}
Попробуйте сами
Напишите, что выведет код: каждый вывод с новой строки.
Показать ответ и разбор
Коротко
Код выведет: 4000 4000, 1 7 5, 0 7 7. Атомарный счётчик (даже с relaxed) и счётчик под мьютексом дают точные 4000: инкременты не теряются, а join гарантирует, что все записи видны основному потоку.
Что выведет
4000 4000
1 7 5
0 7 7
Разбор
Атомарный счётчик (даже с relaxed) и счётчик под мьютексом дают точные 4000: инкременты не теряются, а join гарантирует, что все записи видны основному потоку. Первый CAS: x == expected == 5, записывается 7, expected не меняется. Второй CAS: x == 7 ≠ 5, запись не происходит, в expected попадает текущее значение 7.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.
Ещё по теме «Многопоточность и модель памяти»
- Найти потенциальный дедлок по порядку захвата мьютексов
- Пул потоков: кто и когда выполнит задачу
- Публикация данных через флаг
- Ловушка std::async
- Потокобезопасная ленивая инициализация
- compare_exchange
- Ожидание на condition_variable
- Что такое гонка данных