Namespaces
Variants

std::counting_semaphore<LeastMaxValue>:: acquire

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
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
void acquire ( ) ;
(desde C++20)

Decrementa atómicamente el contador interno en 1 si es mayor que 0 ; de lo contrario, se bloquea hasta que sea mayor que 0 y pueda decrementar exitosamente el contador interno.

Contenidos

Precondiciones

(ninguno)

Parámetros

(ninguno)

Excepciones

Puede lanzar std::system_error .

Ejemplo

El ejemplo visualiza el trabajo concurrente de varios hilos aleatorizados cuando no más de N (N es el valor deseado del semáforo) de las funciones-hilo están activas, mientras que las demás pueden esperar en el semáforo.

#include <array>
#include <chrono>
#include <cstddef>
#include <iomanip>
#include <iostream>
#include <mutex>
#include <new>
#include <random>
#include <semaphore>
#include <thread>
#include <vector>
using namespace std::literals;
constexpr std::size_t max_threads{10U}; // cambia y observa el efecto
constexpr std::ptrdiff_t max_sema_threads{3}; // {1} para semáforo binario
std::counting_semaphore semaphore{max_sema_threads};
constexpr auto time_tick{10ms};
unsigned rnd()
{
    static std::uniform_int_distribution<unsigned> distribution{2U, 9U}; // [delays]
    static std::random_device engine;
    static std::mt19937 noise{engine()};
    return distribution(noise);
}
class alignas(std::hardware_destructive_interference_size) Guide
{
    inline static std::mutex cout_mutex;
    inline static std::chrono::time_point<std::chrono::high_resolution_clock> started_at;
    unsigned delay{rnd()}, occupy{rnd()}, wait_on_sema{};
public:
    static void start_time() { started_at = std::chrono::high_resolution_clock::now(); }
    void initial_delay() { std::this_thread::sleep_for(delay * time_tick); }
    void occupy_sema()
    {
        wait_on_sema =
            static_cast<unsigned>(std::chrono::duration_cast<std::chrono::milliseconds>(
                std::chrono::high_resolution_clock::now() - started_at -
                delay * time_tick).count() / time_tick.count());
        std::this_thread::sleep_for(occupy * time_tick);
    }
    void visualize(unsigned id, unsigned x_scale = 2) const
    {
        auto cout_n = [=](auto str, unsigned n)
        {
            for (n *= x_scale; n-- > 0; std::cout << str)
                ;
        };
        std::lock_guard lk{cout_mutex};
        std::cout << '#' << std::setw(2) << id << ' ';
        cout_n("░", delay);
        cout_n("▒", wait_on_sema);
        cout_n("█", occupy);
        std::cout << '\n';
    }
    static void show_info()
    {
        std::cout << "\nHilos: " << max_threads << ", Rendimiento: " << max_sema_threads
                  << " │ Leyenda: retraso inicial ░░ │ estado de espera ▒▒ │ ocupación del semáforo ██ \n"
                  << std::endl;
    }
};
std::array<Guide, max_threads> guides;
void workerThread(unsigned id)
{
    guides[id].initial_delay(); // simular algún trabajo antes de la adquisición del semáforo
    semaphore.acquire();        // esperar hasta que haya un espacio libre disponible en el semáforo
    guides[id].occupy_sema();   // simular algún trabajo mientras se adquiere el semáforo
    semaphore.release();
    guides[id].visualizar(id);
}
int main()
{
    std::vector<std::jthread> threads;
    threads.reserve(max_threads);
    Guide::show_info();
    Guide::start_time();
    for (auto id{0U}; id != max_threads; ++id)
        threads.push_back(std::jthread(workerThread, id));
}

Salida posible:

Caso por defecto: max_threads{10U}, max_sema_threads{3}
Hilos: 10, Rendimiento: 3 │ Leyenda: retardo inicial ░░ │ estado de espera ▒▒ │ ocupación del semáforo ██
# 1 ░░░░██████
# 2 ░░░░████████
# 5 ░░░░░░██████████
# 8 ░░░░░░░░░░░░████████████
# 9 ░░░░░░░░░░░░██████████████
# 7 ░░░░░░░░░░░░▒▒▒▒████████████████
# 4 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒████████
# 6 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒██████████████████
# 3 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████████████
# 0 ░░░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████████████
──────────────────────────────────────────────────────────────────────────────────────────────────────────────
Caso "Suficiente para todos" (¡sin estados de espera!): max_threads{10U}, max_sema_threads{10}
Hilos: 10, Rendimiento: 10 │ Leyenda: retardo inicial ░░ │ estado de espera ▒▒ │ ocupación del semáforo ██
# 4 ░░░░██████
# 5 ░░░░░░████
# 3 ░░░░██████████
# 1 ░░░░██████████
# 8 ░░░░░░░░████████████
# 6 ░░░░░░░░░░░░░░░░██████
# 7 ░░░░░░░░░░░░░░░░██████
# 9 ░░░░░░░░░░░░░░░░██████████
# 0 ░░░░░░░░░░░░██████████████████
# 2 ░░░░░░░░░░░░░░░░░░████████████
──────────────────────────────────────────────────────────────────────────────────────────────────────────────
Caso de semáforo binario: max_threads{10U}, max_sema_threads{1}
Hilos: 10, Rendimiento: 1 │ Leyenda: retardo inicial ░░ │ estado de espera ▒▒ │ ocupación del semáforo ██
# 6 ░░░░████
# 5 ░░░░▒▒▒▒████
# 4 ░░░░░░░░░░▒▒██████████
# 7 ░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒████████████████
# 2 ░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████
# 3 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████████████████
# 0 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████████████
# 1 ░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████████
# 8 ░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████
# 9 ░░░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████████████

Véase también

incrementa el contador interno y desbloquea los adquirientes
(función de miembro pública)
intenta decrementar el contador interno sin bloquear
(función de miembro pública)
intenta decrementar el contador interno, bloqueando hasta por un tiempo de duración
(función de miembro pública)
intenta decrementar el contador interno, bloqueando hasta un punto en el tiempo
(función de miembro pública)