Namespaces
Variants

std:: counting_semaphore, std:: binary_semaphore

From cppreference.net
Concurrency support library
Threads
(C++11)
(C++20)
this_thread namespace
(C++11)
(C++11)
Cooperative cancellation
Mutual exclusion
Generic lock management
Condition variables
(C++11)
Semaphores
counting_semaphore binary_semaphore
(C++20) (C++20)
Latches and Barriers
(C++20)
(C++20)
Futures
(C++11)
(C++11)
(C++11)
Safe reclamation
Hazard pointers
Atomic types
(C++11)
(C++20)
Initialization of atomic types
(C++11) (deprecated in C++20)
(C++11) (deprecated in C++20)
Memory ordering
(C++11) (deprecated in C++26)
Free functions for atomic operations
Free functions for atomic flags
Определено в заголовочном файле <semaphore>
template < std:: ptrdiff_t LeastMaxValue = /* implementation-defined */ >
class counting_semaphore ;
(1) (since C++20)
using binary_semaphore = std :: counting_semaphore < 1 > ;
(2) (since C++20)
1) Семафор-счётчик counting_semaphore — это облегчённый примитив синхронизации, который может контролировать доступ к общему ресурсу. В отличие от std::mutex , семафор-счётчик counting_semaphore позволяет более чем одному одновременному доступу к одному и тому же ресурсу, как минимум для LeastMaxValue одновременных обращений. Программа некорректна, если LeastMaxValue является отрицательным.
2) binary_semaphore является псевдонимом для специализации std::counting_semaphore с LeastMaxValue равным 1 . Реализации могут реализовывать binary_semaphore более эффективно, чем стандартная реализация std::counting_semaphore .

Семафор счётчика counting_semaphore содержит внутренний счётчик, инициализируемый конструктором. Этот счётчик уменьшается при вызовах acquire() и связанных методов, и увеличивается при вызовах release() . Когда счётчик равен нулю, acquire() блокируется до тех пор, пока счётчик не будет увеличен, однако try_acquire() не блокируется; try_acquire_for() и try_acquire_until() блокируются до увеличения счётчика или достижения таймаута.

Подобно std::condition_variable::wait() , counting_semaphore 's try_acquire() может ложно завершаться неудачей.

Специализации std::counting_semaphore не являются DefaultConstructible , CopyConstructible , MoveConstructible , CopyAssignable или MoveAssignable .

Содержание

Члены данных

Название члена Определение
counter (private) Внутренний счетчик типа std::ptrdiff_t .
( объект-член только для демонстрации* )

Функции-члены

конструирует counting_semaphore
(публичная функция-член)
уничтожает counting_semaphore
(публичная функция-член)
operator=
[deleted]
counting_semaphore не может быть присвоен
(публичная функция-член)
Операции
увеличивает внутренний счетчик и разблокирует ожидающих
(публичная функция-член)
уменьшает внутренний счетчик или блокируется до возможности
(публичная функция-член)
пытается уменьшить внутренний счетчик без блокировки
(публичная функция-член)
пытается уменьшить внутренний счетчик, блокируясь на указанное время
(публичная функция-член)
пытается уменьшить внутренний счетчик, блокируясь до указанного момента времени
(публичная функция-член)
Константы
[static]
возвращает максимально возможное значение внутреннего счетчика
(публичная статическая функция-член)

Примечания

Как следует из названия, LeastMaxValue является минимальным максимальным значением, а не фактическим максимальным значением. Следовательно, max() может возвращать число большее, чем LeastMaxValue .

В отличие от std::mutex , counting_semaphore не привязан к потокам выполнения - захват семафора может происходить в другом потоке, чем освобождение семафора, например. Все операции с counting_semaphore могут выполняться конкурентно и без какой-либо привязки к конкретным потокам выполнения, за исключением деструктора, который не может выполняться конкурентно, но может быть выполнен в другом потоке.

Семафоры также часто используются для семантики сигнализации/уведомления, а не для взаимного исключения, путем инициализации семафора значением 0 и, таким образом, блокировки получателей, пытающихся вызвать acquire() , до тех пор пока отправитель не "подаст сигнал" путем вызова release ( n ) . В этом отношении семафоры можно рассматривать как альтернативу std::condition_variable , часто с более высокой производительностью.

Макрос тестирования возможностей Значение Стандарт Функция
__cpp_lib_semaphore 201907L (C++20) std::counting_semaphore , std::binary_semaphore

Пример

#include <chrono>
#include <iostream>
#include <semaphore>
#include <thread>
// глобальные экземпляры бинарного семафора
// счетчики объектов установлены в ноль
// объекты находятся в неподписанном состоянии
std::binary_semaphore
    smphSignalMainToThread{0},
    smphSignalThreadToMain{0};
void ThreadProc()
{
    // ожидание сигнала от основного процесса
    // путем попытки уменьшить счетчик семафора
    smphSignalMainToThread.acquire();
    // этот вызов блокируется до тех пор, пока счетчик семафора
    // не будет увеличен из основного процесса
    std::cout << "[thread] Got the signal\n"; // ответное сообщение
    // ожидание 3 секунды для имитации
    // выполнения работы потоком
    using namespace std::literals;
    std::this_thread::sleep_for(3s);
    std::cout << "[thread] Send the signal\n"; // сообщение
    // сигнализировать основному процессу
    smphSignalThreadToMain.release();
}
int main()
{
    // создать рабочий поток
    std::thread thrWorker(ThreadProc);
    std::cout << "[main] Send the signal\n"; // сообщение
    // сигнализировать рабочему потоку начать работу
    // путем увеличения счетчика семафора
    smphSignalMainToThread.release();
    // ожидать завершения работы рабочим потоком
    // путем попытки уменьшить счетчик семафора
    smphSignalThreadToMain.acquire();
    std::cout << "[main] Got the signal\n"; // ответное сообщение
    thrWorker.join();
}

Вывод:

[main] Send the signal
[thread] Got the signal
[thread] Send the signal
[main] Got the signal