TGViewer
C++ geek C++ geek @cpp_geek · 3.53K subscribers
Post #414 1.34K
🚦 Многопоточность без тормозов: std::atomic против std::mutex

Мы все знаем классику: если несколько потоков одновременно пишут в одну переменную, случается Data Race (гонка данных), и программа выдает мусор или падает.

Первое, чему нас учат - ставьте std::mutex. Но мьютексы могут убить производительность вашего приложения.

🐢 Почему std::mutex такой медленный?
Мьютекс - это тяжеловесный механизм операционной системы.
Если Поток А захватил мьютекс, а Поток Б пытается сделать то же самое, ОС видит, что «дверь закрыта». ОС усыпляет Поток Б (происходит Context Switch) и отдает ядро процессора кому-то другому. Когда Поток А отпускает мьютекс, ОС должна снова «разбудить» Поток Б.

Смена контекста и пробуждение — это тысячи потерянных тактов процессора. Использовать мьютекс ради того, чтобы просто сделать counter++ - это как вызывать спецназ, чтобы разнять дерущихся котят.

🚀 Решение: std::atomic (Lock-Free магия)
Вместо того чтобы просить ОС усыплять потоки, мы можем использовать std::atomic. Он работает на уровне самого железа (процессора).



Для атомиков компилятор генерирует специальные ассемблерные инструкции (например, с префиксом LOCK на архитектуре x86). Процессор сам на аппаратном уровне гарантирует, что инкремент произойдет неделимо (атомарно). Никаких обращений к ОС, никаких засыпаний!

🆚 Давайте сравним в коде:


// 🐢 ТЯЖЕЛОВЕСНО (std::mutex)
std::mutex mtx;
int counter = 0;

void AddMutex() {
std::lock_guard<std::mutex> lock(mtx);
counter++; // Заморозили поток ОС ради одной операции!
}



// 🚀 БЕЗ БЛОКИРОВОК (std::atomic)
std::atomic<int> counter = 0;

void AddAtomic() {
counter++; // Выполняется за наносекунды на уровне CPU
}


Разница в скорости на простых операциях типа счетчиков или флагов может достигать 50-100 раз в пользу std::atomic!

⚖️ Когда что использовать?

Нельзя просто взять и везде заменить мьютексы на атомики.
• ✅ Используйте std::atomic, если вам нужно защитить только одну простую переменную (счетчик метрик, флаг остановки bool, указатель на узел в lock-free очереди).

• 🛑 Используйте std::mutex, если вам нужно выполнить сложную логику, защитить кусок памяти (std::vector, std::map) или обновить сразу две и более переменных одновременно.

💡 Итог: Многопоточность - это искусство компромисса. Оставляйте тяжелые замки (mutex) для больших комнат, а для маленьких сейфов (int, bool) используйте умные аппаратные ключи (atomic).

#cpp #multithreading #atomic #mutex #optimization #coding #tips

➡️ @cpp_geek
  • 👍 6
  • ❤ 2
More from @cpp_geek
  1. Sep 24, 2026🎥 Вебинар по C++: Паттерн многопоточного программирования «Producer-Consumer» Когда неско…
  2. Sep 24, 2026Execution policy для параллельных алгоритмов Execution policy в C++ — это новшество, введе…
  3. Sep 17, 2026В чем разница между git fetch и git pull? Разница между этими командами заключается в том,…
  4. Sep 15, 2026std::tie std::tie — это функция, которая создает кортеж ссылок на lvalue из своих аргумент…
  5. Sep 11, 2026move constructor Move-конструктор — это специальный конструктор, который позволяет эффекти…
  6. Sep 9, 2026Move-only объекты и почему std::unique_ptr нельзя копировать Многие удивляются, когда комп…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →