c++唤醒指定的线程 c++20

1.概要

2.内容

在C++中,唤醒指定的线程通常涉及使用条件变量(std::condition_variable)或信号量(如std::semaphore,C++20引入)等同步机制。这些机制允许一个线程等待(阻塞)另一个线程的通知(唤醒)。

以下是一个使用std::condition_variable来唤醒指定线程的示例:

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void worker_thread() {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [] { return ready; });
    std::cout << "Worker thread has been woken up!" << std::endl;
}

void notifier_thread() {
    std::this_thread::sleep_for(std::chrono::seconds(2)); // Simulate some work
    {
        std::lock_guard<std::mutex> lock(mtx);
        ready = true;
    }
    cv.notify_one();
}

int main() {
    std::thread worker(worker_thread);
    std::thread notifier(notifier_thread);

    worker.join();
    notifier.join();

    return 0;
}

在这个示例中:

  1. worker_thread 函数中的线程会等待条件变量 cv
  2. notifier_thread 函数中的线程模拟一些工作(通过 std::this_thread::sleep_for 等待2秒),然后设置 ready 为 true 并通知等待的线程(cv.notify_one())。
  3. 当 worker_thread 被唤醒后,它会打印一条消息。

使用 std::semaphore

如果你使用的是C++20或更新的标准,你也可以使用 std::semaphore 来实现相同的功能。以下是一个使用 std::semaphore 的示例:

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

std::semaphore sem(0);

void worker_thread() {
    sem.acquire();
    std::cout << "Worker thread has been woken up!" << std::endl;
}

void notifier_thread() {
    std::this_thread::sleep_for(std::chrono::seconds(2)); // Simulate some work
    sem.release();
}

int main() {
    std::thread worker(worker_thread);
    std::thread notifier(notifier_thread);

    worker.join();
    notifier.join();

    return 0;
}

在这个示例中:

  1. worker_thread 函数中的线程会等待信号量 sem
  2. notifier_thread 函数中的线程模拟一些工作(通过 std::this_thread::sleep_for 等待2秒),然后释放信号量(sem.release())。
  3. 当 worker_thread 被唤醒后,它会打印一条消息。

这两种方法都可以有效地唤醒指定的线程,具体使用哪种方式取决于你的使用场景和C++标准版本。

3.关联知识

1.std::semaphore

std::semaphore 是 C++20 标准库中新增的一个同步原语,用于管理多个线程对共享资源的访问。它允许你控制同时访问某个特定资源或代码段的线程数量。std::semaphore 提供了一种机制,通过计数器来跟踪当前有多少线程可以进入临界区(即访问共享资源的代码段)。

基本概念

  • 计数(Count)std::semaphore 的核心是一个计数器,它表示当前还可以有多少线程进入临界区。当计数器的值为 0 时,表示没有更多的线程可以进入临界区,直到有其他线程离开并释放信号量,计数器的值才会增加。
  • 等待(Wait):当一个线程想要进入临界区时,它会尝试“等待”信号量。如果信号量的计数器大于 0,则线程可以进入临界区,并且计数器的值会减 1。如果计数器的值为 0,则线程会被阻塞,直到有其他线程释放信号量。
  • 通知(Signal):当一个线程完成临界区的操作后,它会“通知”信号量,即增加计数器的值。这可能会唤醒一个正在等待进入临界区的线程。

主要成员函数

  • 构造函数std::semaphore(unsigned int count); 创建一个信号量,初始计数为 count
  • waitvoid wait(); 尝试减少信号量的计数。如果计数为 0,则线程会被阻塞直到计数大于 0。
  • try_waitbool try_wait(); 尝试减少信号量的计数。如果计数大于 0,则减少并返回 true;如果计数为 0,则立即返回 false 而不阻塞线程。
  • notifyvoid notify(); 增加信号量的计数。如果有线程因为计数为 0 而被阻塞,则唤醒其中一个线程。

使用场景

std::semaphore 非常适合用于控制对资源的并发访问,比如限制同时访问某个数据库连接的线程数量,或者限制同时执行某个特定任务的线程数量。

示例代码

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

std::semaphore sem(3); // 允许最多3个线程同时进入临界区

void access_resource(int id) {
    sem.wait(); // 等待进入临界区
    std::cout << "Thread " << id << " is accessing the resource.\n";
    // 模拟资源访问
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::cout << "Thread " << id << " is leaving the resource.\n";
    sem.notify(); // 离开临界区,通知其他线程
}

int main() {
    std::vector<std::thread> threads;
    for (int i = 0; i < 5; ++i) {
        threads.emplace_back(access_resource, i);
    }
    for (auto& t : threads) {
        t.join();
    }
    return 0;
}

在这个示例中,我们创建了一个初始计数为 3 的 std::semaphore,表示最多允许 3 个线程同时访问资源。然后,我们创建了 5 个线程,每个线程都尝试访问资源。由于信号量的限制,只有 3 个线程可以同时进入临界区,其他线程必须等待直到有线程离开并释放信号量。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值