信号量:
本质:计数器
作用:实现进程或线程间的同步与互斥
操作:
P操作:判断计数器是否大于0,大于0则表示有资源,则计数-1,正确返回,计数<=0表示没有资源,则阻塞
V操作:增加一个资源计数(计数器+1),唤醒一个阻塞的进程或线程
同步实现:计数器用于对资源的数量进行统计,通过资源数量决定是否可获取资源同步
线程A在获取资源之前进行P操作;线程B在产生一个资源后进行V操作
互斥实现:通过一个只有1的计数器,来表示资源只有一个,同一时间只有一个线程能访问
线程在访问资源之前进行P操作;线程B在产生一个资源后进行V操作。
接口:
sem_t; sem_init(); sem_wait() / sem_trywait() / sem_timedwait() sem_post() sem_destroy*)
线程池:一个或多个线程+线程安全的任务队列
应用场景:有大量的数据请求需要并发处理的场景
工作流程:管理线程不断的将任务加入到任务队列中,线程池中的线程不断的从任务队列中取出任务进行处理。
好处:
避免了瞬时峰值压力下资源耗尽的风险
节省了任务处理时创建和销毁的时间成本
实现:
创建指定数量的线程
线程安全的任务队列
重点:
线程池只是一个执行流的池子,本身并不知道一个任务如何处理,因此设计了一个任务类:
template<class T>
class ThreadTask{
private:
T_data;
std::function<void(T)>_handler;
public:
void start(){ return _handler(_data);}
};
Template<class T>
class ThreadPool{
private:
int _max_thread;
BlockQueue<ThreadTask<T>>_queue;
public:
ThreadPool(){//完成线程的创建}
bool Push(ThreadTask<T>&task);
}
单例模式:非常典型的一种设计模式
设计模式:针对典型场景所设计的解决方案
单例模式针对的场景:一个类只能实例化一个对象
资源角度:资源在内存中只能有一份
数据角度:如果只有一个对象,则数据无论什么时候获取都是一致的
单例模式实现:对象只有一个 提供一个访问接口进行访问
饿汉模式:直接对象实例化完毕,资源申请完毕,以便于用的时候随时能用
饿汉实现:
将对象设置为静态资源,这样就可以在程序的初始化阶段完成实例化。
懒汉模式:对象要用的时候再去实例化,资源用到时候再去申请
懒汉实现:
对象在用的时候再去实例化