欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 美景 > C++:std::thread、条件变量与信号量

C++:std::thread、条件变量与信号量

2025/2/23 15:33:29 来源:https://blog.csdn.net/qq_43441284/article/details/145740965  浏览:    关键词:C++:std::thread、条件变量与信号量

介绍

在多线程编程的世界里,协调不同线程之间的工作是一项极具挑战性的任务。线程可能需要等待特定条件的满足,或者对共享资源的访问进行限制。C++ 标准库为我们提供了强大的工具,如 std::thread 用于创建和管理线程,条件变量用于线程间的同步,信号量则用于控制对资源的访问。本文将通过具体的 C++ 代码示例,详细介绍如何使用这些工具。

std::thread 基础

std::thread 是 C++11 引入的用于创建和管理线程的类。它允许我们轻松地在程序中创建新的执行线程。下面是一个简单的 std::thread

#include <iostream>
#include <thread>void printMessage(const std::string& message) {std::cout << "Thread says: " << message << std::endl;
}int main() {std::thread t(printMessage, "Hello, World!");t.join();return 0;
}

定义了一个函数 printMessage,然后使用 std::thread 创建了一个新线程,并将 printMessage 函数作为线程的入口点,同时传递了一个字符串参数。join() 方法用于等待线程执行完毕。

条件变量

条件变量是一种同步原语,用于线程之间的通信和协调。它允许一个线程等待某个条件的满足,而另一个线程可以在条件满足时通知等待的线程。
生产者 - 消费者模型示例
生产者 - 消费者模型是多线程编程中常见的模式,生产者线程负责生产数据,消费者线程负责消费数据。我们可以使用条件变量来实现线程间的同步。

#include <iostream>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>std::queue<int> dataQueue;
std::mutex mtx;
std::condition_variable cv;
bool isProducing = true;// 生产者线程函数
void producer() {for (int i = 0; i < 5; ++i) {std::this_thread::sleep_for(std::chrono::seconds(1));{std::unique_lock<std::mutex> lock(mtx);dataQueue.push(i);std::cout << "Produced: " << i << std::endl;}cv.notify_one();}{std::unique_lock<std::mutex> lock(mtx);isProducing = false;}cv.notify_one();
}//消费者线程函数
void consumer() {while (true) {std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, [] { return!dataQueue.empty() ||!isProducing; });if (!dataQueue.empty()) {int value = dataQueue.front();dataQueue.pop();std::cout << "Consumed: " << value << std::endl;} else if (!isProducing) {break;}}
}int main() {std::thread producerThread(producer);std::thread consumerThread(consumer);producerThread.join();consumerThread.join();return 0;
}

std::queue dataQueue:用于存储生产者生产的数据。
std::mutex mtx:用于保护对 dataQueue 的访问,确保线程安全。
std::condition_variable cv:用于线程间的同步。
producer() 函数:生产者线程每隔 1 秒生产一个数据,并将其加入队列。生产完成后,通知消费者线程。
consumer() 函数:消费者线程等待条件变量的通知,当队列中有数据时,从队列中取出数据进行消费。
cv.wait(lock, [] { return!dataQueue.empty() ||!isProducing; }):消费者线程等待,直到队列非空或者生产结束。

信号量

信号量是一种用于控制对资源访问的同步原语。在 C++ 标准库中,并没有直接提供信号量的实现,可以使用 std::mutex 和 std::condition_variable 来模拟信号量。
信号量的实现

#include <mutex>
#include <condition_variable>class Semaphore {
public:Semaphore(int count = 0) : count_(count) {}void notify() {std::unique_lock<std::mutex> lock(mtx_);++count_;cv_.notify_one();}void wait() {std::unique_lock<std::mutex> lock(mtx_);cv_.wait(lock, [this] { return count_ > 0; });--count_;}private:int count_;std::mutex mtx_;std::condition_variable cv_;
};
#include <iostream>
#include <thread>
#include <vector>Semaphore sem(2); // 允许最多 2 个线程同时访问资源void accessResource(int id) {sem.wait();std::cout << "Thread " << id << " is accessing the resource." << std::endl;std::this_thread::sleep_for(std::chrono::seconds(2));std::cout << "Thread " << id << " has finished accessing the resource." << std::endl;sem.notify();
}int main() {std::vector<std::thread> threads;for (int i = 0; i < 5; ++i) {threads.emplace_back(accessResource, i);}for (auto& t : threads) {t.join();}return 0;
}

Semaphore 类:实现了一个简单的信号量。notify() 方法用于增加信号量的值并通知等待的线程,wait() 方法用于等待信号量的值大于 0 并减少信号量的值。
accessResource() 函数:线程在访问资源前调用 sem.wait() 等待信号量,访问完成后调用 sem.notify() 释放信号量。
emplace_back 是 C++ 标准库容器(如 std::vector、std::deque 等)提供的一个成员函数,它主要用于在容器的尾部直接构造一个新元素。

结论

通过 std::thread、条件变量和信号量,可以在 C++ 中实现复杂的多线程程序。条件变量用于线程间的同步,确保线程在特定条件满足时才继续执行;信号量用于控制对资源的访问,避免资源竞争。合理使用这些工具可以提高程序的性能和稳定性。希望本文能帮助你更好地理解和应用这些多线程编程的重要概念。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词