C++ 框架中实现并发和多线程处理的常见模式

在现代软件开发中,随着硬件性能的提升和多核处理器的普及,并发和多线程编程变得越来越重要。C++作为一种高级编程语言,提供了丰富的工具和框架来实现并发和多线程处理。本文将介绍在C++框架中常见的并发和多线程处理模式。

线程创建与管理

std::thread

C++11引入了标准库中的std::thread类,用于创建和管理线程。使用std::thread,我们可以创建新线程并指定其要执行的函数或可调用对象。

#include <iostream>

#include <thread>

void foo() {

std::cout << "Running in a separate thread" << std::endl;

}

int main() {

std::thread t(foo);

t.join(); // 等待线程t执行完毕

return 0;

}

在上述代码中,我们创建了一个新线程t来执行函数foo。主线程通过调用join函数等待新线程执行完毕。

线程池

线程池是一种预先创建的线程集合,可以复用线程来处理多个任务,从而避免频繁创建和销毁线程带来的开销。Boost库提供了线程池的实现,也有第三方库如ThreadPool。

#include <iostream>

#include <vector>

#include <thread>

#include <queue>

#include <functional>

#include <condition_variable>

class ThreadPool {

public:

ThreadPool(size_t threads);

~ThreadPool();

template <class F, class... Args>

auto enqueue(F&& f, Args&&... args)

-> std::future<typename std::result_of<F(Args...)>::type>;

private:

// 处理线程池中的任务

std::vector<std::thread> workers;

// 存储任务的队列

std::queue<std::function<void()>> tasks;

// 同步机制

std::mutex queue_mutex;

std::condition_variable condition;

bool stop;

};

inline ThreadPool::ThreadPool(size_t threads)

: stop(false) {

for (size_t i = 0; i < threads; ++i)

workers.emplace_back(

[this] {

for (;;) {

std::function<void()> task;

{

std::unique_lock<std::mutex> lock(this->queue_mutex);

this->condition.wait(lock,

[this] { return this->stop || !this->tasks.empty(); });

if (this->stop && this->tasks.empty())

return;

task = std::move(this->tasks.front());

this->tasks.pop();

}

task();

}

}

);

}

template <class F, class... Args>

auto ThreadPool::enqueue(F&& f, Args&&... args)

-> std::future<typename std::result_of<F(Args...)>::type>

{

using return_type = typename std::result_of<F(Args...)>::type;

auto task = std::make_shared<std::packaged_task<return_type()>>(

std::bind(std::forward<F>(f), std::forward<Args>(args)...)

);

std::future<return_type> res = task->get_future();

{

std::unique_lock<std::mutex> lock(queue_mutex);

if (stop)

throw std::runtime_error("enqueue on stopped ThreadPool");

tasks.emplace([task](){ (*task)(); });

}

condition.notify_one();

return res;

}

inline ThreadPool::~ThreadPool() {

{

std::unique_lock<std::mutex> lock(queue_mutex);

stop = true;

}

condition.notify_all();

for (std::thread &worker: workers)

worker.join();

}

上面的代码展示了一个基本的线程池实现。ThreadPool类管理了一组工作线程和一个任务队列,支持任务的异步提交。

任务调度与同步

std::async

std::async是C++11中引入的另一个用于并发执行任务的工具。它允许我们启动一个异步任务,并返回一个std::future对象,该对象可以用于获取任务的返回值。

#include <iostream>

#include <future>

int foo() {

return 42;

}

int main() {

std::future<int> result = std::async(std::launch::async, foo);

std::cout << "The answer is " << result.get() << std::endl;

return 0;

}

在上述代码中,我们使用std::async启动了一个异步任务foo,并通过std::future对象result获取并打印了该任务的返回值。

同步原语

为了确保多线程访问共享资源时的一致性和正确性,我们需要使用同步原语,例如互斥量、条件变量和锁。

#include <iostream>

#include <thread>

#include <mutex>

std::mutex mtx;

void print_thread_id(int id) {

std::lock_guard<std::mutex> lock(mtx);

std::cout << "Thread ID: " << id << std::endl;

}

int main() {

std::thread t1(print_thread_id, 1);

std::thread t2(print_thread_id, 2);

t1.join();

t2.join();

return 0;

}

在上述代码中,我们使用std::mutex和std::lock_guard确保对标准输出的访问是线程安全的。

总结

C++提供了多种并发和多线程处理模式,包括直接使用std::thread创建和管理线程,使用线程池优化线程创建开销,以及使用std::async进行任务调度。同时,通过使用互斥量和条件变量等同步原语,我们可以确保多线程程序的正确性和一致性。合理运用这些模式,可以大幅提升程序的性能和响应速度。

后端开发标签