跳至主要內容

55.C++线程控制_信号量

约 428 字大约 1 分钟

计数信号量 std::counting_semaphore

#include <iostream>
#include <thread>
#include <semaphore>  // C++20

std::counting_semaphore<3> sem(3); // 计数信号量,最多允许 3 个线程访问

void worker(int id) {
    sem.acquire();  // 获取信号量
    std::cout << "线程 " << id << " 进入临界区\n";
    std::this_thread::sleep_for(std::chrono::seconds(1)); // 模拟工作
    std::cout << "线程 " << id << " 退出临界区\n";
    sem.release();  // 释放信号量
}

int main() {
    std::thread threads[5];
    for (int i = 0; i < 5; ++i)
        threads[i] = std::thread(worker, i + 1);

    for (auto& t : threads)
        t.join();

    return 0;
}

二进制信号量 std::binary_semaphore

#include <iostream>
#include <thread>
#include <semaphore>  // C++20

std::binary_semaphore semA(1); // 初始允许线程 A 运行
std::binary_semaphore semB(0); // 线程 B 需要等待

void threadA() {
    for (int i = 0; i < 5; ++i) {
        semA.acquire();  // 等待信号
        std::cout << "A" << std::endl;
        semB.release();  // 通知线程 B
    }
}

void threadB() {
    for (int i = 0; i < 5; ++i) {
        semB.acquire();  // 等待线程 A
        std::cout << "B" << std::endl;
        semA.release();  // 通知线程 A
    }
}

int main() {
    std::thread t1(threadA);
    std::thread t2(threadB);

    t1.join();
    t2.join();

    return 0;
}

经典生产者-消费者模型

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

std::counting_semaphore<1> empty_slots(1); // 1 个空槽位(生产者等待)
std::counting_semaphore<0> filled_slots(0); // 0 个数据(消费者等待)
std::mutex mtx; // 保护共享队列
std::queue<int> buffer; // 共享缓冲区

void producer() {
    for (int i = 1; i <= 5; ++i) {
        empty_slots.acquire();  // 等待空槽
        {
            std::lock_guard<std::mutex> lock(mtx);
            buffer.push(i);
            std::cout << "生产者:生产数据 " << i << std::endl;
        }
        filled_slots.release();  // 通知消费者
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
    }
}

void consumer() {
    for (int i = 1; i <= 5; ++i) {
        filled_slots.acquire();  // 等待数据
        {
            std::lock_guard<std::mutex> lock(mtx);
            int value = buffer.front();
            buffer.pop();
            std::cout << "消费者:消费数据 " << value << std::endl;
        }
        empty_slots.release();  // 通知生产者
        std::this_thread::sleep_for(std::chrono::milliseconds(800));
    }
}

int main() {
    std::thread t1(producer);
    std::thread t2(consumer);

    t1.join();
    t2.join();

    return 0;
}