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 ( ) ;
(seit C++20)

Dekrementiert atomar den internen Zähler um 1 falls dieser größer als 0 ist; andernfalls blockiert er, bis er größer als 0 ist und den internen Zähler erfolgreich dekrementieren kann.

Inhaltsverzeichnis

Vorbedingungen

(keine)

Parameter

(keine)

Ausnahmen

Kann std::system_error werfen.

Beispiel

Das Beispiel visualisiert die gleichzeitige Arbeit mehrerer randomisierter Threads, wenn nicht mehr als N (N ist der Semaphor- desired Wert) der Thread-Funktionen aktiv sind, während die anderen möglicherweise auf den Semaphor warten.

#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::Literale;
constexpr std::size_t max_threads{10U}; // Ändern und die Auswirkung sehen
constexpr std::ptrdiff_t max_sema_threads{3}; // {1} für binären Semaphor
std::counting_semaphore semaphore{max_sema_threads};
constexpr auto time_tick{10ms};
unsigned rnd()
{
    static std::uniform_int_distribution<unsigned> distribution{2U, 9U}; // [Verzögerungen]
    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
(Keine Übersetzung erforderlich, da der Text innerhalb der HTML-Tags C++-spezifische Begriffe enthält und gemäß den Anweisungen nicht übersetzt werden soll)<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
**Erklärung:**
- HTML-Tags und Attribute wurden unverändert beibehalten
- C++-spezifische Begriffe (`std::chrono::high_resolution_clock::now`) wurden nicht übersetzt
- Die ursprüngliche Formatierung wurde vollständig erhalten
- Da der gesamte sichtbare Text innerhalb des Links C++-Code ist, wurde keine Übersetzung vorgenommen(); }
    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 << "\nThreads: " << max_threads << ", Durchsatz: " << max_sema_threads
                  << " │ Legende: Anfangsverzögerung ░░ │ Wartezustand ▒▒ │ Semaphor-Belegung ██ \n"
                  << std::endl;
    }
};
std::array<Guide, max_threads> guides;
void workerThread(unsigned id)
{
    guides[id].initial_delay(); // simuliere einige Arbeit vor Semaphor-Erwerb
    semaphore.acquire();        // warten, bis ein freier Semaphor-Slot verfügbar ist
    guides[id].occupy_sema();   // simuliere einige Arbeit während Semaphor gehalten wird
    semaphore.release();
    guides[id].visualisieren(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));
}

Mögliche Ausgabe:

Standardfall: max_threads{10U}, max_sema_threads{3}
Threads: 10, Durchsatz: 3 │ Legende: anfängliche Verzögerung ░░ │ Wartezustand ▒▒ │ Semaphor-Belegung ██
# 1 ░░░░██████
# 2 ░░░░████████
# 5 ░░░░░░██████████
# 8 ░░░░░░░░░░░░████████████
# 9 ░░░░░░░░░░░░██████████████
# 7 ░░░░░░░░░░░░▒▒▒▒████████████████
# 4 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒████████
# 6 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒██████████████████
# 3 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████████████
# 0 ░░░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████████████
──────────────────────────────────────────────────────────────────────────────────────────────────────────────
"Genug für alle"-Fall (keine Wartezustände!): max_threads{10U}, max_sema_threads{10}
Threads: 10, Durchsatz: 10 │ Legende: anfängliche Verzögerung ░░ │ Wartezustand ▒▒ │ Semaphor-Belegung ██
# 4 ░░░░██████
# 5 ░░░░░░████
# 3 ░░░░██████████
# 1 ░░░░██████████
# 8 ░░░░░░░░████████████
# 6 ░░░░░░░░░░░░░░░░██████
# 7 ░░░░░░░░░░░░░░░░██████
# 9 ░░░░░░░░░░░░░░░░██████████
# 0 ░░░░░░░░░░░░██████████████████
# 2 ░░░░░░░░░░░░░░░░░░████████████
──────────────────────────────────────────────────────────────────────────────────────────────────────────────
Binärer Semaphor-Fall: max_threads{10U}, max_sema_threads{1}
Threads: 10, Durchsatz: 1 │ Legende: anfängliche Verzögerung ░░ │ Wartezustand ▒▒ │ Semaphor-Belegung ██
# 6 ░░░░████
# 5 ░░░░▒▒▒▒████
# 4 ░░░░░░░░░░▒▒██████████
# 7 ░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒████████████████
# 2 ░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████
# 3 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████████████████
# 0 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████████████
# 1 ░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████████
# 8 ░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████
# 9 ░░░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████████████

Siehe auch

erhöht den internen Zähler und entblockiert Akquisiteure
(öffentliche Elementfunktion)
versucht, den internen Zähler ohne Blockierung zu dekrementieren
(öffentliche Elementfunktion)
versucht, den internen Zähler zu dekrementieren, blockiert für maximal eine Zeitdauer
(öffentliche Elementfunktion)
versucht, den internen Zähler zu dekrementieren, blockiert bis zu einem Zeitpunkt
(öffentliche Elementfunktion)