c++线程库基本原理

本文探讨C++线程库的基本原理,通过代码展示如何初始化线程、实现线程上锁与解锁,以及等待信号通知进行任务执行。线程池仅支持不返回值且带任意参数的函数,如lambda表达式,暂无异常处理功能。
摘要由CSDN通过智能技术生成

最近没更新博客,今天来写下c++线程库的基本原理,直接上代码

思路:
1 初始化线程
2 线程上锁 -> 然后解除锁的占用 -> 等待信号通知
3 某个线程被通知到后 -> 获取锁 -> 锁获取后取任务队里第一个任务函数 -> 解除锁 -> 执行任务 -> 继续第二步操作

关键点:信号通知函数 notify_one() ,只会通知等待区中的一个,让其来获取锁, 避免惊群事件。
该线程池只支持空值返回的任意参数的函数(lambda),没有异常处理,算是个基本雏形吧。看注释就能理解。

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

using namespace std;

class ThreadPool
{
public:
	ThreadPool(size_t threads)
	{
		// 初始指定数量的线程
		for (size_t i = 0; i < threads; ++i)
		{
			// emplace_back避免拷贝插入
			m_works.emplace_back([this] {

				while (true)
				{
					function<void()> task;

					{
						// 申请队列互斥锁
						unique_lock<mutex> lock(this->m_mutex);

						// 释放锁的占用,等待条件通知, 强制停止或者有任务
						this->m_condition.wait(lock, [this] 
						{ 
							return this->m_stop || !this->m_queueTasks.empty(); 
						});

						// 线程池退出,并且任务队列中没有任务 线程退出
						if (this->m_stop && this->m_queueTasks.empty()) 
						{
							break;
						}

						// 取任务队中第一并弹出
						task = move(this->m_queueTasks.front());
						this->m_queueTasks.pop();

						// 锁的作用域范围结束,释放互斥锁
					}

					// 运行任务
					task();
				}
			});
		}
	}

	~ThreadPool()
	{
		{	// 申请锁,置stop
			unique_lock<mutex> lock(m_mutex);
			m_stop = true;
		}

		// 通知所有临界区的等待结束
		m_condition.notify_all();

		// 等待所有线程退出
		for (thread& t : m_works)
		{
			t.join();
		}
	}

	template<class F, class... Args>
	void addTask(F&& f, Args&&... args)
	{
		// bind函数地址及参数
		auto task = bind(forward<F>(f), forward<Args>(args)...);

		{
			// 申请锁
			unique_lock<mutex> lock(m_mutex);

			// 强制停止不能再加任务
			if (m_stop) 
			{
				cout << "pool is stop!" << endl;
				return;
			}

			// 添加
			m_queueTasks.emplace(task);

			// 锁释放
		}

		// 在等待区的一个被通知,避免惊群
		m_condition.notify_one();
	}

private:
	vector<thread>	m_works;					// 线程集合
	queue<function<void()>> m_queueTasks;		// 等待运行的任务队列

	mutex m_mutex;					// 任务队列的互斥锁
	condition_variable m_condition;	// 条件变量

	bool m_stop;	// 终止所有线程
};


void testTaskInt(int i) 
{
	cout << "task int" << i << " process!" << endl;
}

void testTaskString(string s)
{
	cout << "task string " << s.c_str() << " processs!" << endl;
}
int _tmain()
{
	{
		ThreadPool pool(4);

		// 任务函数bind参数
		pool.addTask(&testTaskInt, 1);
		pool.addTask(&testTaskString, "hello world!");

		// lamda函数
		int i = 999;
		string s = "hello lamda";
		pool.addTask([i, s]
		{
			cout << "task lamda " << i << s.c_str() << "process!" << endl;
		});


		this_thread::sleep_for(chrono::seconds(10));
	}

	// pool 销毁
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值