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

内部カウンタが 1 より大きい場合、アトミックに内部カウンタを 0 デクリメントする。それ以外の場合、カウンタが 0 より大きくなり、内部カウンタのデクリメントが正常に実行できるまでブロックする。

目次

事前条件

(なし)

パラメータ

(なし)

例外

以下の例外をスローする可能性があります std::system_error

この例は、いくつかのランダム化されたスレッドが同時に動作する様子を可視化したものです。セマフォの desired 値であるNを超えない数のスレッド関数のみがアクティブで、それ以外のスレッドはセマフォで待機する可能性があります。

#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::リテラル;
constexpr std::size_t max_threads{10U}; // 変更して効果を確認
constexpr std::ptrdiff_t max_sema_threads{3}; // {1} バイナリセマフォ用
std::counting_semaphore semaphore{max_sema_threads};
constexpr auto time_tick{10ms};
unsigned rnd()
{
    static std::uniform_int_distribution<unsigned> distribution{2U, 9U}; // [遅延]
    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
(注:指示に従い、HTMLタグ・属性、C++固有用語(std::chrono::high_resolution_clock::now)は翻訳対象外として保持しました。表示されるテキスト部分が全てC++用語のため、翻訳対象となる自然言語テキストが存在しません)(); }
    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
(注:指示に従い、HTMLタグ・属性、タグ内のC++識別子は翻訳対象外のため、元のまま保持されています)() - 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 << "\nスレッド数: " << max_threads << ", スループット: " << max_sema_threads
                  << " │ 凡例: 初期遅延 ░░ │ 待機状態 ▒▒ │ セマフォ占有 ██ \n"
                  << std::endl;
    }
};
std::array<Guide, max_threads> guides;
void workerThread(unsigned id)
{
    guides[id]
(注:元のテキストは閉じ括弧のみのため、日本語でも同じ記号を保持します).initial_delay(); // セマフォ取得前の作業をエミュレート
    semaphore.acquire();        // 空きセマスロットが利用可能になるまで待機
    guides[id].occupy_sema();   // セマフォ取得中に何らかの作業をエミュレート
    semaphore.release();
    guides[id].visualize(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));
}

出力例:

デフォルトケース: max_threads{10U}, max_sema_threads{3}
スレッド数: 10, スループット: 3 │ 凡例: 初期遅延 ░░ │ 待機状態 ▒▒ │ セマフォ占有 ██
# 1 ░░░░██████
# 2 ░░░░████████
# 5 ░░░░░░██████████
# 8 ░░░░░░░░░░░░████████████
# 9 ░░░░░░░░░░░░██████████████
# 7 ░░░░░░░░░░░░▒▒▒▒████████████████
# 4 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒████████
# 6 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒██████████████████
# 3 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████████████
# 0 ░░░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████████████
──────────────────────────────────────────────────────────────────────────────────────────────────────────────
「全員に十分」ケース(待機状態なし!): max_threads{10U}, max_sema_threads{10}
スレッド数: 10, スループット: 10 │ 凡例: 初期遅延 ░░ │ 待機状態 ▒▒ │ セマフォ占有 ██
# 4 ░░░░██████
# 5 ░░░░░░████
# 3 ░░░░██████████
# 1 ░░░░██████████
# 8 ░░░░░░░░████████████
# 6 ░░░░░░░░░░░░░░░░██████
# 7 ░░░░░░░░░░░░░░░░██████
# 9 ░░░░░░░░░░░░░░░░██████████
# 0 ░░░░░░░░░░░░██████████████████
# 2 ░░░░░░░░░░░░░░░░░░████████████
──────────────────────────────────────────────────────────────────────────────────────────────────────────────
バイナリセマフォケース: max_threads{10U}, max_sema_threads{1}
スレッド数: 10, スループット: 1 │ 凡例: 初期遅延 ░░ │ 待機状態 ▒▒ │ セマフォ占有 ██
# 6 ░░░░████
# 5 ░░░░▒▒▒▒████
# 4 ░░░░░░░░░░▒▒██████████
# 7 ░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒████████████████
# 2 ░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████
# 3 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████████████████
# 0 ░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████████████
# 1 ░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒████████
# 8 ░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████
# 9 ░░░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████████████

関連項目

内部カウンタをインクリメントし、取得側のブロックを解除します
(公開メンバ関数)
ブロックせずに内部カウンタをデクリメントしようと試みます
(公開メンバ関数)
内部カウンタのデクリメントを試み、最大で指定時間までブロックします
(公開メンバ関数)
内部カウンタのデクリメントを試み、指定時点までブロックします
(公開メンバ関数)