一、同步异步
同步:当一个同步调用发出后,调用者要一直等待返回消息(或者调用结果)通知后,才能进行后续的执行;
异步:当一个异步过程调用发出后,调用者不能立刻得到返回消息(结果)。实际处理这个调用的部件在完成后,通过消息回调来通知调用者是否调用成功。
同步与异步着重点在消息通知的方式,也就是调用结果通知的方式。
二、半同步半异步
同步模式编程简单,但是I/O的利用利率低;而异步模式编程复杂,但是I/O利用率高。综合同步异步的有优点,就有了半同步半异步的设计模式。高层使用同步I/O模型,简化编程。低层使用异步I/O模型,高效执行。【1】主线程只管理监听socket、连接,得到新的连接socket由工作线程来管理。当有新的连接到来时,主线程就接受并将新返回的连接socket派发给某个工作线程,此后,该socket上任何I/O操作都由被选中的工作线程来处理,知道客户端关闭连接。【2】主线程向工作线程派发socket的方式,是往它和工作线程之间的管道里写数据。工作线程检测到管道上有数据可读时,就分析是否是一个新的客户端连接请求到来,如果是,就把该socket上的读写事件注册到自己的epoll内核事件表中。【3】此模式每个线程都维持自己的事件循环,各自监听不同的事件。
优缺点:
优点:
上层的任务被简化
不同层可以使用不同的同步策略
层间的通信被限制在单独的一点,因为所有的交互使用队列层协调。
缺点:
跨边界导致的性能消耗,这是因为同步控制,数据拷贝和上下文切换会过度地消耗资源。
上层任务缺少异步I/O的实现。
同步队列:
#include <list>
#include <mutex>
#include <thread>
#include <condition_variable>
#include <iostream>
using namespace std;
template<typename T>
class SyncQueue
{
public:
/*构造函数*/
SyncQueue( int maxSize ) : m_maxSize( maxSize ), m_needStop( false )
{
}
/*添加事件,左值拷贝和右值引用*/
void Put( const T&x )
{
/*调用private内部接口Add*/
Add( x );
}
void Put( T &&x )
{
Add( std::forward<T>(x) );
}
/*从队列中取事件*/
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(); //唤醒阻塞的线程
}
/*取一个线程*/
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 Stop()
{
{
std::lock_guard<std::mutex> locker(m_mutex);
m_needStop = true;
}
m_notFull.notify_all();
m_notEmpty.notify_all();
}
bool Empty()
{
std::lock_guard<std::mutex> locker(m_mutex);
return m_queue.empty();
}
bool full()
{
std::lock_guard<std::mutex> locker(m_mutex);
return m_queue.size == m_maxSize;
}
size_t Size()
{
std::lock_guard<std::mutex> locker(m_mutex);
return m_queue.size();
}
int Count()
{
return m_queue.size();
}
private:
bool NotFull() const
{
bool full = m_queue.size() >= m_maxSize;
if( full )
{
cout << "缓冲区满了,需要等待..." << endl;
}
return !full;
}
bool NotEmpty() const
{
bool empty = m_queue.empty();
if( empty )
{
cout << "缓冲区空了,需要等待...异步层线程ID:" << std::this_thread::get_id() << endl;
}
return !empty;
}
template<typename F>
void Add( F &&x )
{
std::unique_lock<std::mutex> locker(m_mutex);
m_notFull.wait( locker, [this]{return m_needStop || NotFull(); } ); //
if( m_needStop )
{
return ;
}
m_queue.push_back(std::forward<F>(x)); //条件满足,像队列添加事件
m_notEmpty.notify_one(); //唤等待的工作线程
}
private:
std::list<T> m_queue; //缓冲区
std::mutex m_mutex; //互斥量和条件变量结合使用
std::condition_variable m_notEmpty; //不为空的条件变量
std::condition_variable m_notFull; //没有满的条件变量
int m_maxSize; //同步队列最大的size
bool m_needStop; //停止的标志
};
线程池:
#include <iostream>
#include <list>
#include <thread>
#include <functional>
#include <memory>
#include <atomic>
#include "pthread_queue.cpp"
using namespace std;
const int MaxTaskCount = 100;
class ThreadPool
{
public:
//规定任务类型为void,funciton可为任意函数,即可处理任意任务
using Task = std::function<void()>;
//hardware_concurrency检测硬件性能,给出默认线程数
ThreadPool( int numThreads = std::thread::hardware_concurrency()): m_queue(MaxTaskCount)
{
Start(numThreads);
}
~ThreadPool(void)
{
//如果没有停止则主动停止线程池
Stop();
}
//call_once保证StopThreadGroup只被调用一次
void Stop()
{
std::call_once(m_flag, [this]{StopThreadGroup(); });
}
//普通形式和右值引用的添加任务
//添加很多任务
void AddTask(Task &&task)
{
m_queue.Put(std::forward<Task>(task));
}
//添加一个任务
void AddTaskk(const Task &task)
{
m_queue.Put(task);
}
void Start( int numThreads )
{
m_running = true;
//创建线程组
for( int i=0; i<numThreads; ++i )
{
cout << " Init create thread pool " << endl;
m_threadgroup.push_back(std::make_shared<std::thread>(&ThreadPool::RunInThread, this));
}
}
private:
void RunInThread()
{
while( m_running )
{
std::list<Task> list;
cout << "take\n";
m_queue.Take(list);
for(auto &task : list)
{
if(!m_running)
return ;
task();
}
}
}
void StopThreadGroup()
{
//让同步队列中的线程停止
m_queue.Stop();
m_running = false;
for(auto thread : m_threadgroup)
{
if(thread)
{
thread->join();
}
}
m_threadgroup.clear();
}
private:
std::list<std::shared_ptr<std::thread>> m_threadgroup; //处理任务的线程组
SyncQueue<Task> m_queue; //同步队列
atomic_bool m_running; //是否停止的标志
std::once_flag m_flag;
};
int main( int argc, char *argv[] )
{
ThreadPool pool(2);
std::thread thd1([&pool]{
for( int i=0; i<10; i++ )
{
auto thdId = std::this_thread::get_id();
pool.AddTask([thdId]{
std::cout << thdId << "thread execute task"<< std::endl;
});
}
});
std::this_thread::sleep_for(std::chrono::seconds(2));
pool.Stop();
thd1.join();
return EXIT_SUCCESS;
}