threadpool线程池

 线程池源码

#pragma once

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <queue>
#include <functional>
#include <memory>
#include <future>

class ThreadPool
{
public:
	ThreadPool(uint32_t size) : stop(false)
	{
		for (int i = 0; i < size; ++i)
		{
			works.emplace_back([this]() {
				while (true) {
					std::function<void()> task;
					{
						std::unique_lock<std::mutex> lock(queueMtx);
						cv.wait(lock, [this]()->bool {
							return stop || !tasks.empty();
						});
						if (stop && tasks.empty())
							return;

						task = tasks.front();
						tasks.pop();
					}
					task();
				}

			});
		}
	}
	~ThreadPool()
	{
		{
			std::unique_lock<std::mutex> lock(queueMtx);
			stop = true;
		}

		cv.notify_all();
		for (auto &work : works)
			work.join();
	}
	template<class Func, class ...Arg>
	auto enqueue(Func &&f, Arg ...args) -> std::future<typename std::invoke_result<Func, Arg...>::type>
	{
		using return_type = typename std::invoke_result<Func, Arg...>::type;
		auto task = std::make_shared<std::packaged_task<return_type()>>(std::bind(std::forward<Func>(f), std::forward<Arg>(args)...));
		std::future<return_type> res = task->get_future();
		{
			std::unique_lock<std::mutex> lock(queueMtx);
			if (stop)
				throw("thread pool is stop");
			tasks.emplace([task]() {(*task)(); });
			cv.notify_one();
		}

		return res;
	}
private:
	bool stop;
	std::vector<std::thread> works;
	std::queue<std::function<void()>> tasks;
	std::mutex queueMtx;
	std::condition_variable cv;
};

线程池源码分析

1,condition_variable:

条件变量(condition variable):在C++11中实现多个线程之间的同步操作,当条件不满足时,相关线程一直被阻塞,直到某种条件成立,这些线程才会被唤醒。

条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包含两个动作:

一个线程因为等待条件变量的条件成立而挂起,
另外一个线程使条件成立,给出信号,从而唤醒被等待的线程。
为了防止竞争,条件变量总是和一个互斥锁结合在一起,通常情况下这个锁是 std::mutex,并且管理这个锁的只能是 std::unique_lock<std::mutex> RAII 的模板类。

这里我们使用condition_variable实现线程同步,当没有任务执行时,condition_variable使线程处于等待状态,当有任务进入队列后,调用notify_one唤醒一个等待的线程处理任务,处理完成后线程又恢复到等待状态等待下一次被唤醒。

2, std::unique_lock<std::mutex>:

        std::unique_lock 相对于 std::lock_guard 出现的,对比来说, std::unique_lock 更加灵活,
std::unique_lock 的对象会以独占所有权(没有其他的 unique_lock 对象同时拥有某个 mutex
对象的所有权)的方式管理 mutex 对象上的上锁和解锁的操作。所以在并发编程中,推荐使用
std::unique_lock
        std::lock_guard 不能显式的调用 lock unlock ,而 std::unique_lock 可以在声明后的任意位
置调用,可以缩小锁的作用范围,提供更高的并发度。
        如果你用到了条件变量 std::condition_variable::wait 则必须使用 std::unique_lock 作为参
数。
        配合std::mutex使用,管理std::mutex的上锁与解锁。
3,std::mutex
        std::mutex 是 C++11 中最基本的 mutex 类,通过实例化 std::mutex 可以创建互斥量,而通过
其成员函数 lock() 可以进行上锁, unlock() 可以进行解锁。但是在在实际编写代码的过程中,最好不 去直接调用成员函数,因为调用成员函数就需要在每个临界区的出口处调用 unlock() ,当然,还包括异 常。这时候 C++11 还为互斥量提供了一个 RAII 语法的模板类 std::lock_guard RAII 在不失代码简洁性的同时,很好的保证了代码的异常安全性。
        配合condition_variable使用,实现线程同步。
4,std::future

std::future是C++11标准库(并发支持库)中的一个模板类,它表示一个异步操作的结果。当我们在多线程编程中使用异步任务时,std::future可以帮助我们在需要的时候获取任务的执行结果。std::future的一个重要特性是能够阻塞当前线程,直到异步操作完成,从而确保我们在获取结果时不会遇到未完成的操作。

作用

  1. 异步操作的结果获取:std::future提供了一种机制,允许我们在多线程环境中安全地获取异步操作的结果。
  2. 隐藏异步操作的细节:std::future将异步操作的结果封装起来,使程序员无需关注线程同步和通信的具体实现细节。
  3. 线程同步:通过阻塞等待异步操作完成,std::future可以确保我们在继续执行其他操作之前,已经获取了所需的结果。
  4. 异常处理:std::future可以捕获异步操作中抛出的异常,并在获取结果时重新抛出,也可以在主线程中对其进行处理,从而使得异常处理更加简单。
  5. 提高性能:std::future使得我们能够更好地利用多核处理器的性能,通过并行执行任务来提高程序的执行效率。
        这里我们使用std::future来保存线程执行后的结果,然后将线程计算结果返回给主线程。

5,std::packaged_task

       td::packaged_task 将任何可调用对象(比如函数、lambda 表达式等等)封装成一个 task,可以异步执行。执行结果可以使用 std::future 获取

6,std::bind

std::bind将可调用对象与其参数一起进行绑定,绑定后的结果可以使用std::function保存。std::bind主要有以下两个作用:

  • 将可调用对象和其参数绑定成一个仿函数;
  • 只绑定部分参数,减少可调用对象传入的参数。

7,std::forward

        实现参数完美转发

8,queue

        任务队列,先进先出,保存待执行的任务。

9,vector

向量,用于保存线程对象,后面管理线程。

测试程序

#include "threadpool.h"

int main(void)
{
	int size = 4;
	int a = 0;
	int b = 0;
	ThreadPool threadpool(size);

	for (int i = 0; i < size; ++i)
	{
		a = i * 3;
		b = (i + 1) * 2;
		auto res = threadpool.enqueue([a, b]()->int {return a + b; });

		std::cout << "a = " << a << " b = " << b << " res = " << res.get()<< std::endl;
	}

	return 0;
}
  • 15
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

瞎折腾啥啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值