免费行情网站app下载大全,南昌网站排名优化价格,南山区住房与建设局官方网站,大淘客联盟做网站线程池
线程池的逻辑思想#xff1a; 每当我们处理一个任务就要创建一个线程#xff0c;创建线程的开销是很大的。因此我们可以预先创建一批线程#xff0c;任务队列里没有任务的时候#xff0c;每个线程都休眠#xff0c;当队里中有任务的时候#xff0c;就可以唤醒线程…线程池
线程池的逻辑思想 每当我们处理一个任务就要创建一个线程创建线程的开销是很大的。因此我们可以预先创建一批线程任务队列里没有任务的时候每个线程都休眠当队里中有任务的时候就可以唤醒线程进行处理。唤醒线程的成本比创建整个线程的成本小这就是线程池的逻辑思想。 线程池的概念 线程池: 一种线程使用模式。线程过多会带来调度开销进而影响缓存局部性和整体性能。而线程池维护着多个线程等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用还能防止过分调度。可用线程数量应该取决于可用的并发处理器、处理器内核、内存、网络sockets等的数量。 线程池常见的应用场景 需要大量的线程来完成任务且完成任务的时间比较短。 对性能要求苛刻的应用比如要求服务器迅速响应客户请求。 接受突发性的大量请求但不至于使服务器因此产生大量线程的应用。 代码实现
首先我们先熟悉一下整体的框架 Thread.hpp
#pragma once
#include pthread.h
#include iostream
#include cassert
#include string
#include functional
namespace ThreadNs
{typedef std::functionvoid*(void*) func_t;const int num 1024;class Thread{private:static void* start_routine(void*args){Thread* _this static_castThread*(args);return _this-callback();}public:Thread(){char namebuffer[num];snprintf(namebuffer,sizeof namebuffer,thread-%d,threadnum);name_ namebuffer;}void start(func_t func,void*args nullptr){func_ func;args_ args;int n pthread_create(tid_,nullptr,start_routine,this);assert(n0);(void)n;}void join(){int n pthread_join(tid_,nullptr);assert(n0);(void)n;}std::string threadname(){return name_;}~Thread(){}void* callback(){return func_(args_);}private:std::string name_;func_t func_;void *args_;pthread_t tid_;static int threadnum;};int Thread::threadnum 1;
}LockGuard.hpp
#include iostream
#include mutex
class Mutex
{
public:Mutex(pthread_mutex_t*lock_pnullptr):lock_p_(lock_p){}void lock(){if(lock_p_) pthread_mutex_lock(lock_p_);}void unlock(){if(lock_p_) pthread_mutex_unlock(lock_p_);}~Mutex(){}
private:pthread_mutex_t * lock_p_;
};
class LockGuard
{
public:LockGuard(pthread_mutex_t*mutex):mutex_(mutex){mutex_.lock();}~LockGuard(){mutex_.unlock();}
private:Mutex mutex_;
};ThreadPool.hpp
#pragma once
#include Thread.hpp
#include LockGuard.hpp
#include vector
#include queue
#include pthread.h
#include mutex
#include unistd.h
using namespace ThreadNs;
const int gnum 3;
template class T
class ThreadPool;template class T
class ThreadData
{
public:ThreadPoolT *threadpool;std::string name;
public:ThreadData(ThreadPoolT *tp, const std::string n) : threadpool(tp), name(n){ }
};
template class T
class ThreadPool
{
private:static void *handlerTask(void *args){ThreadDataT *td (ThreadDataT *)args;ThreadPoolT *threadpool static_castThreadPoolT *(args);while (true){T t;{LockGuard lockguard(td-threadpool-mutex());while(td-threadpool-isQueueEmpty()){td-threadpool-threadWait();}t td-threadpool-pop(); }std::cout td-name 获取了一个任务 t.toTaskString() 并处理完成结果是: t() std::endl;}delete td;return nullptr;}
public:void lockQueue() { pthread_mutex_lock(_mutex); }void unlockQueue() { pthread_mutex_unlock(_mutex); }bool isQueueEmpty() { return _task_queue.empty(); }void threadWait() { pthread_cond_wait(_cond, _mutex); }T pop(){T t _task_queue.front();_task_queue.pop();return t;}void Push(const T in){LockGuard lockguard(_mutex);_task_queue.push(in);pthread_cond_signal(_cond);}pthread_mutex_t *mutex(){return _mutex;}public:ThreadPool(const int num gnum) : _num(num){pthread_mutex_init(_mutex, nullptr);pthread_cond_init(_cond, nullptr);for (int i 0; i _num; i){_threads.push_back(new Thread());}}void run(){for (const auto t : _threads){ThreadDataT *td new ThreadDataT(this, t-threadname());t-start(handlerTask, td);std::cout t-threadname() start... std::endl;}}~ThreadPool(){pthread_mutex_destroy(_mutex);pthread_cond_destroy(_cond);for (const auto t : _threads)delete t;}
private:int _num;std::vectorThread * _threads;std::queueT _task_queue;pthread_mutex_t _mutex;pthread_cond_t _cond;
};我们将线程池进行了模板化因此线程池当中存储的任务类型可以是任意的现在我们想像之前处理各种数据的计算那么先引入任务组件Task.hpp
#pragma once
#include iostream
#include functional
class Task
{using func_t std::functionint(int,int ,char);
public:Task(){}Task(int x,int y,char op,func_t func):_x(x),_y(y),_op(op),_callback(func){}std::string operator()(){int result _callback(_x,_y,_op);char buffer[1024];snprintf(buffer,sizeof buffer,%d %c %d %d,_x,_op,_y,result);return buffer;}std::string toTaskString(){char buffer[1024];snprintf(buffer,sizeof buffer,%d %c %d ?,_x,_op,_y);return buffer;}
private:int _x;int _y;char _op;func_t _callback;
};const std::string oper -*/%;
int mymath(int x,int y,char op)
{int result 0;switch(op){case :result xy;break;case -:result x-y;break;case *:result x*y;break;case /:if(y0){std::cerrdiv zero error!std::endl;result -1;}else{result x/y;}break;case %:if(y0){std::cerrmod zero error!std::endl;result -1;}else{result x%y;}break;default:break;}return result;
}main.cc
#include ThreadPool.hpp
#include Thread.hpp
#include Task.hpp
#include unistd.h
#include ctime
int main()
{ThreadPoolTask* tp new ThreadPoolTask();tp-run();srand(time(0));int x,y;char op;while(true){x rand()%101;y rand()%201;op oper[rand()%oper.size()];Task t(x,y,op,mymath);tp-Push(t);sleep(1);}return 0;
}单例模式 单例模式是一种创建型设计模式它保证一个类只有一个实例存在并且提供一个全局访问点来访问该实例。单例模式有饿汉模式和懒汉模式。 洗完的例子 吃完饭 , 立刻洗碗 , 这种就是 饿汉方式 . 因为下一顿吃的时候可以立刻拿着碗就能吃饭 . 吃完饭 , 先把碗放下 , 然后下一顿饭用到这个碗了再洗碗 , 就是 懒汉方式 . 饿汉实现方式和懒汉实现方式
饿汉方式实现单例模式
template typename T
class Singleton {
static T data;
public:
static T* GetInstance() {
return data;
}
}; 懒汉方式实现单例模式
template typename T
class Singleton {
static T* inst;
public:
static T* GetInstance() {
if (inst NULL) {
inst new T();
}
return inst;
}
};
这样的懒汉设计可能会导致线程不安全第一次调用 GetInstance 的时候, 如果两个线程同时调用, 可能会创建出两份 T 对象的实例。因此以下才是安全版的懒汉单例模式 // 懒汉模式 , 线程安全 template typename T class Singleton { volatile static T* inst; // 需要设置 volatile 关键字 , 否则可能被编译器优化 . static std::mutex lock; public: static T* GetInstance() { if (inst NULL) { // 双重判定空指针 , 降低锁冲突的概率 , 提高性能 . lock.lock(); // 使用互斥锁 , 保证多线程情况下也只调用一次 new. if (inst NULL) { inst new T(); } lock.unlock(); } return inst; } }; 线程池的单例模式
我们要做的第一步就是把构造函数私有再把拷贝构造和赋值运算符重载delete 接下来就要在成员变量中定义一个静态指针方便获取单例对象 在设置获取单例对象的函数的时候注意要设置成静态成员函数因为在获取对象前根本没有对象无法调用非静态成员函数无this指针: 主函数的调用 不过也许会出现多个线程同时申请资源的场景所以还需要一把锁来保护这块资源而这把锁也得设置成静态因为GetSingle()函数是静态的 STL,智能指针和线程安全 STL 的设计初衷是将性能挖掘到极致 , 而一旦涉及到加锁保证线程安全 , 会对性能造成巨大的影响 . 而且对于不同的容器, 加锁方式的不同 , 性能可能也不同 ( 例如 hash 表的锁表和锁桶 ). 因此 STL 默认不是线程安全 . 如果需要在多线程环境下使用 , 往往需要调用者自行保证线程安全 . 对于 unique_ptr, 由于只是在当前代码块范围内生效, 因此不涉及线程安全问题.对于 shared_ptr, 多个对象需要共用一个引用计数变量, 所以会存在线程安全问题. 但是标准库实现的时候考虑到了这个问题, 基于原子操作(CAS)的方式保证 shared_ptr 能够高效, 原子的操作引用计数. 其他常见的各种锁 悲观锁在每次取数据时总是担心数据会被其他线程修改所以会在取数据前先加锁读锁写锁行锁等当其他线程想要访问数据时被阻塞挂起。 乐观锁每次取数据时候总是乐观的认为数据不会被其他线程修改因此不上锁。但是在更新数据前会判断其他数据在更新前有没有对数据进行修改。主要采用两种方式版本号机制和CAS操作。 CAS操作当需要更新数据时判断当前内存值和之前取得的值是否相等。如果相等则用新值更新。若不等则失败失败则重试一般是一个自旋的过程即不断重试 自旋锁使用自旋锁时当多线程发生竞争锁的情况时加锁失败的线程会忙等待这里的忙等待可以用 while 循环等待实现直到它拿到锁。而互斥锁加锁失败后线程会让出 CPU 资源给其他线程使用然后该线程会被阻塞挂起。如果成功申请临界资源的线程临界区代码执行时间过长自旋的线程会长时间占用 CPU 资源所以自旋的时间和临界区代码执行的时间是成正比的关系。如果临界区代码执行的时间很短就不应该使用互斥锁而应该选用自旋锁。因为互斥锁加锁失败是需要发生上下文切换的如果临界区执行的时间比较短那可能上下文切换的时间会比临界区代码执行的时间还要长。 读者和写者问题 读者写者问题和生产者消费者模型的本质区别就是消费者会取走数据而读者不会取走数据。
读写锁接口 //初始化读写锁 pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr); //销毁读写锁 pthread_rwlock_destroy(pthread_rwlock_t *rwlock); //读加锁 pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); //写加锁 pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock); //解锁 pthread_rwlock_unlock(pthread_rwlock_t *rwlock); 文章转载自: http://www.morning.qxkjy.cn.gov.cn.qxkjy.cn http://www.morning.ffhlh.cn.gov.cn.ffhlh.cn http://www.morning.dfqmy.cn.gov.cn.dfqmy.cn http://www.morning.mbmtz.cn.gov.cn.mbmtz.cn http://www.morning.sjsfw.cn.gov.cn.sjsfw.cn http://www.morning.cmqrg.cn.gov.cn.cmqrg.cn http://www.morning.scjtr.cn.gov.cn.scjtr.cn http://www.morning.tsmcc.cn.gov.cn.tsmcc.cn http://www.morning.qwbtr.cn.gov.cn.qwbtr.cn http://www.morning.bxgpy.cn.gov.cn.bxgpy.cn http://www.morning.rwhlf.cn.gov.cn.rwhlf.cn http://www.morning.cnqff.cn.gov.cn.cnqff.cn http://www.morning.jxltk.cn.gov.cn.jxltk.cn http://www.morning.dpqwq.cn.gov.cn.dpqwq.cn http://www.morning.redhoma.com.gov.cn.redhoma.com http://www.morning.xdjwh.cn.gov.cn.xdjwh.cn http://www.morning.qfwzm.cn.gov.cn.qfwzm.cn http://www.morning.fkfyn.cn.gov.cn.fkfyn.cn http://www.morning.jfwrf.cn.gov.cn.jfwrf.cn http://www.morning.ryfqj.cn.gov.cn.ryfqj.cn http://www.morning.hhpbj.cn.gov.cn.hhpbj.cn http://www.morning.fpczq.cn.gov.cn.fpczq.cn http://www.morning.wkwds.cn.gov.cn.wkwds.cn http://www.morning.spdyl.cn.gov.cn.spdyl.cn http://www.morning.nrgdc.cn.gov.cn.nrgdc.cn http://www.morning.lsmnn.cn.gov.cn.lsmnn.cn http://www.morning.zpfr.cn.gov.cn.zpfr.cn http://www.morning.jzbjx.cn.gov.cn.jzbjx.cn http://www.morning.gthc.cn.gov.cn.gthc.cn http://www.morning.mhfbf.cn.gov.cn.mhfbf.cn http://www.morning.kdbbm.cn.gov.cn.kdbbm.cn http://www.morning.zqmdn.cn.gov.cn.zqmdn.cn http://www.morning.qrsrs.cn.gov.cn.qrsrs.cn http://www.morning.lsgsn.cn.gov.cn.lsgsn.cn http://www.morning.dsmwy.cn.gov.cn.dsmwy.cn http://www.morning.junyaod.com.gov.cn.junyaod.com http://www.morning.cmhkt.cn.gov.cn.cmhkt.cn http://www.morning.lsmgl.cn.gov.cn.lsmgl.cn http://www.morning.lxlfr.cn.gov.cn.lxlfr.cn http://www.morning.tpmnq.cn.gov.cn.tpmnq.cn http://www.morning.xqbgm.cn.gov.cn.xqbgm.cn http://www.morning.kqylg.cn.gov.cn.kqylg.cn http://www.morning.ppdr.cn.gov.cn.ppdr.cn http://www.morning.phxns.cn.gov.cn.phxns.cn http://www.morning.ydyjf.cn.gov.cn.ydyjf.cn http://www.morning.xhftj.cn.gov.cn.xhftj.cn http://www.morning.kysport1102.cn.gov.cn.kysport1102.cn http://www.morning.ljdd.cn.gov.cn.ljdd.cn http://www.morning.gtmdq.cn.gov.cn.gtmdq.cn http://www.morning.jfxdy.cn.gov.cn.jfxdy.cn http://www.morning.lpqgq.cn.gov.cn.lpqgq.cn http://www.morning.mhmsn.cn.gov.cn.mhmsn.cn http://www.morning.yqwsd.cn.gov.cn.yqwsd.cn http://www.morning.rntyn.cn.gov.cn.rntyn.cn http://www.morning.nwtmy.cn.gov.cn.nwtmy.cn http://www.morning.nlkhr.cn.gov.cn.nlkhr.cn http://www.morning.rddlz.cn.gov.cn.rddlz.cn http://www.morning.lynkz.cn.gov.cn.lynkz.cn http://www.morning.yhplt.cn.gov.cn.yhplt.cn http://www.morning.skbhl.cn.gov.cn.skbhl.cn http://www.morning.bttph.cn.gov.cn.bttph.cn http://www.morning.hongjp.com.gov.cn.hongjp.com http://www.morning.msxhb.cn.gov.cn.msxhb.cn http://www.morning.gslz.com.cn.gov.cn.gslz.com.cn http://www.morning.jqzns.cn.gov.cn.jqzns.cn http://www.morning.mrgby.cn.gov.cn.mrgby.cn http://www.morning.trbxt.cn.gov.cn.trbxt.cn http://www.morning.rfqk.cn.gov.cn.rfqk.cn http://www.morning.addai.cn.gov.cn.addai.cn http://www.morning.pmwhj.cn.gov.cn.pmwhj.cn http://www.morning.tqqfj.cn.gov.cn.tqqfj.cn http://www.morning.spnky.cn.gov.cn.spnky.cn http://www.morning.ktdqu.cn.gov.cn.ktdqu.cn http://www.morning.yllym.cn.gov.cn.yllym.cn http://www.morning.cbtn.cn.gov.cn.cbtn.cn http://www.morning.mtrz.cn.gov.cn.mtrz.cn http://www.morning.bzkgn.cn.gov.cn.bzkgn.cn http://www.morning.pfnrj.cn.gov.cn.pfnrj.cn http://www.morning.qlsbz.cn.gov.cn.qlsbz.cn http://www.morning.dmwjl.cn.gov.cn.dmwjl.cn