РЕПЕТИТОР математика физика информатика
Для школьников и студентов. Подтягивание пробелов. ЦЭ, ЦТ, ОГЭ, ЕГЭ.
Идет набор на ЛЕТО. Жмите для подробностей:)
796 of 815 menu

Класс once_flag

Класс once_flag используется в паре с функцией call_once и позволяет гарантировать, что определенный участок кода будет выполнен ровно один раз, независимо от количества потоков, которые пытаются его выполнить. Объект once_flag не хранит никаких пользовательских данных - он лишь служит флагом состояния, который внутренне синхронизируется. Класс не поддерживает копирование и перемещение, поэтому его следует передавать по ссылке.

Основное применение - однократная инициализация общих ресурсов (например, подключение к базе данных, загрузка конфигурации, создание синглтона) в многопоточной среде.

Синтаксис

#include <mutex> std::once_flag flag; std::call_once(flag, func, args...);

Пример

Давайте рассмотрим простой пример однократной инициализации общего ресурса из двух потоков:

#include <iostream> #include <mutex> #include <thread> using namespace std; once_flag flag; void init() { cout << "init once" << endl; } int main() { thread t1([]{ call_once(flag, init); }); thread t2([]{ call_once(flag, init); }); t1.join(); t2.join(); return 0; }

Результат выполнения кода:

"init once"

Пример

Давайте используем once_flag вместе с лямбда-выражением для инициализации глобальной переменной:

#include <iostream> #include <mutex> #include <thread> using namespace std; once_flag flag; int shared_value = 0; int main() { thread t1([] { call_once(flag, [] { shared_value = 42; cout << "initialized" << endl; }); cout << shared_value << endl; }); thread t2([] { call_once(flag, [] { shared_value = 42; cout << "initialized" << endl; }); cout << shared_value << endl; }); t1.join(); t2.join(); return 0; }

Результат выполнения кода:

"initialized" 42 42

Пример

Давайте проверим, что при вызове из нескольких потоков функция выполнится ровно один раз, используя счетчик:

#include <iostream> #include <mutex> #include <thread> #include <vector> using namespace std; once_flag flag; int counter = 0; void increment() { ++counter; } int main() { vector<thread> threads; for (int i = 0; i < 5; ++i) { threads.emplace_back([] { call_once(flag, increment); }); } for (auto& t : threads) { t.join(); } cout << counter << endl; return 0; }

Результат выполнения кода:

1

Смотрите также

  • функция call_once,
    которая выполняет код ровно один раз
  • класс mutex,
    который обеспечивает базовую синхронизацию
  • класс lock_guard,
    который автоматически блокирует и разблокирует мьютекс
  • класс unique_lock,
    который предоставляет гибкое управление блокировкой
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить