导读:本期聚焦于小伙伴创作的《C++中的std::semaphore是什么?如何用它控制并发资源数》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C++中的std::semaphore是什么?如何用它控制并发资源数》有用,将其分享出去将是对创作者最好的鼓励。

std::semaphore是C++20标准库中新增的同步原语,属于信号量类型,主要用于控制同时访问某一资源或资源池的线程数量,避免过多线程同时操作共享资源引发问题。它内部维护了一个计数器,通过对计数器的增减操作来实现线程的同步与资源访问控制。

C++中的std::semaphore是什么?如何用它控制并发资源数

std::semaphore的核心特性

std::semaphore有两种模板特化形式,分别是std::counting_semaphore<std::ptrdiff_t>std::binary_semaphore,其中std::binary_semaphore本质是计数器最大值仅为1的计数信号量,等价于std::counting_semaphore<1>。其核心操作包含两个部分:

  • acquire操作:尝试减少信号量的计数器,如果计数器大于0则操作成功,计数器减1;如果计数器等于0则当前线程阻塞,直到计数器变为大于0。
  • release操作:增加信号量的计数器,通常会唤醒一个等待中的线程。

如何用std::semaphore控制并发资源数

控制并发资源数的核心思路是:将信号量的初始计数器设置为允许同时访问资源的最大线程数,每个线程访问资源前执行acquire操作,访问完成后执行release操作,这样就能保证同时只有指定数量的线程可以访问资源。

基础使用示例

假设我们有一个最多允许3个线程同时访问的共享资源,使用std::semaphore的实现如下:

#include <iostream>
#include <thread>
#include <vector>
#include <semaphore>
#include <chrono>

// 初始化信号量,最大并发数为3
std::counting_semaphore<3> sem(3);

void access_resource(int thread_id) {
    // 获取信号量,计数器减1,若计数器为0则阻塞等待
    sem.acquire();
    std::cout << "线程" << thread_id << "开始访问共享资源" << std::endl;
    // 模拟资源访问耗时
    std::this_thread::sleep_for(std::chrono::seconds(2));
    std::cout << "线程" << thread_id << "结束访问共享资源" << std::endl;
    // 释放信号量,计数器加1,唤醒等待线程
    sem.release();
}

int main() {
    std::vector<std::thread> threads;
    // 创建10个线程尝试访问资源
    for (int i = 0; i < 10; i++) {
        threads.emplace_back(access_resource, i);
    }
    // 等待所有线程执行完成
    for (auto& t : threads) {
        t.join();
    }
    return 0;
}

上述代码中,信号量初始值为3,因此同一时间最多只有3个线程可以执行到资源访问的逻辑,其余线程会在sem.acquire()处阻塞,直到有线程执行sem.release()释放信号量。

超时控制场景

std::semaphore还提供了带超时的acquire操作try_acquire_fortry_acquire_until,可以避免线程无限阻塞。例如我们设置线程等待信号量最多等待1秒,超时则放弃访问:

#include <iostream>
#include <thread>
#include <semaphore>
#include <chrono>

std::counting_semaphore<2> sem(2);

void try_access(int thread_id) {
    // 尝试获取信号量,最多等待1秒
    if (sem.try_acquire_for(std::chrono::seconds(1))) {
        std::cout << "线程" << thread_id << "成功获取信号量,访问资源" << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(3));
        sem.release();
    } else {
        std::cout << "线程" << thread_id << "等待超时,放弃访问资源" << std::endl;
    }
}

int main() {
    std::thread t1(try_access, 1);
    std::thread t2(try_access, 2);
    std::thread t3(try_access, 3);
    t1.join();
    t2.join();
    t3.join();
    return 0;
}

std::semaphore与其他同步工具的差异

工具类型核心用途计数器特性
std::semaphore控制并发访问资源的数量计数器可自定义最大值,支持增减操作
std::mutex保证互斥访问共享资源无计数器,仅支持锁定和释放两种状态
std::condition_variable线程间的条件等待与唤醒无内置计数器,需配合互斥锁和自定义条件使用

使用注意事项

  • std::semaphore是C++20新增特性,使用时需要编译器支持C++20及以上标准,编译时需要添加对应的标准参数,如-std=c++20
  • release操作的调用次数不能超过信号量的最大计数器值,否则会导致未定义行为。
  • 信号量的acquire和release需要在同一个逻辑流程中配对使用,避免出现信号量泄漏,导致其他线程永久阻塞。

std::semaphoreC++并发控制信号量修改时间:2026-06-16 02:30:34

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。