简介
半同步半异步线程池用的比较多,实现也比较简单。
其中同步层包括同步服务层和排队层,指的是将接收的任务排队,将所有的任务排队到一个队列中,等待处理;
异步层指多个线程处理任务,异步处理层从同步层取出任务,并发处理任务。

同步队列
同步队列属于同步层的内容,主要作用是保证队列中共享数据线程安全,同时也提供新增任务的接口,以及提供取任务的接口。
这里使用C++11的锁、条件变量、右值引用、std::move和std::forward来实现。
同步队列主要包括三个函数,Take、Add和Stop。
Take函数
这里实现重载了两个Take函数,可支持一次获取多个任务,或者一次获取一个任务。
//可一次性获取多个任务,放在list中,减少互斥锁阻塞时间
void Take(std::list<T>& list)
{
std::unique_lock<std::mutex> locker(m_mutex);
m_notEmpty.wait(locker, [this] {return m_needStop || NotEmpty(); });
if (m_needStop)
{
return;
}
list = std::move(m_queue);
m_notFull.notify_one();
}
//获取单个任务
void Take(T& t)
{
std::unique_lock<std::mutex> locker(m_mutex);
m_notEmpty.wait(locker, [this] {return m_needStop || NotEmpty(); });
if (m_needStop)
{
return;
}
t = m_queue.front();
m_queue.pop_front();
m_notFull.notify_one();
}
先创建一个unique *lock 获取 mutex,然后再通过条件变量 m_*notEmpty 来等待判断式。判断式由两个条件组成,一个是停止的标志,另一个是不为空的条件,当不满足任何一个条件时,条件变量会释放 mutex 并将线程置于 waiting 状态,等待其他线程调用 notify_one/notify all 将其唤醒;当满足任何一个条件时,则继续往下执行后面的逻辑,即将队列中的任务取出,并唤醒一个正处于等待状态的添加任务的线程去添加任务。当处于 waiting 状态的线程被 notify_one 或notify all 唤醒时,条件变量会先重新获取 mutex,然后再检查条件是否满足,如果满足,则往下执行,如果不满足,则释放 mutex 继续等待。
Add函数
Add 的过程和 Take 的过程是类似的,也是先获取 mutex,然后检查条件是否满足,不满足条件时,释放 mutex 继续等待,如果满足条件,则将新的任务插入到队列中,并唤醒取任务的线程去取数据。

最低0.47元/天 解锁文章
1107

被折叠的 条评论
为什么被折叠?



