您的位置: 首页 - 站长

wordpress不要焦点图乐陵德州seo公司

当前位置: 首页 > news >正文

wordpress不要焦点图,乐陵德州seo公司,大连网站搭建与推广,做一个网站要怎么做1.描述问题 在完成线程池核心功能功能时#xff0c;没有遇到太大的问题#xff08;Any,Result,Semfore的设计#xff09;#xff0c;在做线程池资源回收时#xff0c;遇到了死锁的问题
1、在ThreadPool的资源回收#xff0c;等待线程池所有线程退出时#xff…1.描述问题 在完成线程池核心功能功能时没有遇到太大的问题Any,Result,Semfore的设计在做线程池资源回收时遇到了死锁的问题         1、在ThreadPool的资源回收等待线程池所有线程退出时发生死锁问题导致进程无法退出 死锁代码 #include threadpool.h#include thread #include iostreamconst int TASK_MAX_THRESHHOLD INT32_MAX; const int THREAD_MAX_THRESHHOLD 100; const int THREAD_MAX_IDLETIME 60;//单位秒//线程池构造 ThreadPool::ThreadPool(): initThreadSize(0), taskSize(0), idleThreadSize(0)//刚开始时还没有线程, curThreadSize(0), taskQueMaxThreshHold(TASK_MAXTHRESHHOLD), threadSizeThreshHold(THREAD_MAXTHRESHHOLD), poolMode(PoolMode::MODEFIXED), isPoolRunning(false) {}//线程池析构 ThreadPool::~ThreadPool() {isPoolRunning_ false;notEmpty_.notify_all();//等待线程池里面所有的线程返回 有两种状态阻塞 正在执行任务中std::uniquelockstd::mutex lock(taskQueMtx);exitCond.wait(lock, -bool {return threads.size() 0; }); }//设置线程池的工作模式 void ThreadPool::setMode(PoolMode mode) {if (checkRunningState())return;poolMode_ mode; }// 设置task任务队列上限阈值 void ThreadPool::setTaskQueMaxThreshHold(int threshhold) {if (checkRunningState())return;taskQueMaxThreshHold_ threshhold; }//设置线程池cached模式下线程阈值 void ThreadPool::setThreadSizeThreshHold(int threshhold) {if (checkRunningState())return;if (poolMode_ PoolMode::MODECACHED){threadSizeThreshHold threshhold;} }// 给线程池提交任务 用户调用该接口传入任务对象生产任务 Result ThreadPool::submitTask(std::shared_ptrTask sp) {//获取锁std::uniquelockstd::mutex lock(taskQueMtx);//线程的通信 等待任务队列有空余// 用户提交任务最长不能阻塞超过1s,否则判断提交任务失败返回//while (taskQue.size() taskQueMaxThreshHold)//{// notFull_.wait(lock);//}/** wait:直到等待满足条件第二个参数lamada才返回* wait_for:满足条件返回真,到了约定的时间段5s返回假* waituntil:满足条件返回真,到了约定的时间点下周一返回假*/if (!notFull.waitfor(lock, std::chrono::seconds(1),-bool {return taskQue.size() (sizet)taskQueMaxThreshHold; }))//等同于上面的语句参数需要释放的锁 函数对象(要能满足条件变量//任务队列中的任务数小于上限的阈值否则就阻塞在这句{//表示notFull等待1s条件依然没有满足std::cerr task queue is full,submit task fail. std::endl;//return task-getResult(); //Task Result 线程执行完tasktask对象就被析构掉了return Result(sp, false);//返回临时对象应该自动匹配右值的资源转移如果编译不通过把C标准调高一点}//如果有空余把任务放入任务队列中taskQue.emplace(sp);taskSize_;//因为新放了任务任务队列肯定不空了在notEmpty上进行通知,赶快分配线程执行任务notEmpty.notifyall();//cached模式 任务处理比较紧急 场景小而快的任务 需要根据任务数量和空闲线程的数量判断是否需要创建新的线程出来if (poolMode PoolMode::MODECACHED taskSize idleThreadSize_ curThreadSize_ threadSizeThreshHold_){std::cout create new thread… std::this_thread::get_id() exit! std::endl;//创建新的线程对象auto ptr std::make_uniqueThread(std::bind(ThreadPool::threadFunc, this, std::placeholders::1));int threadId ptr-getId();threads.emplace(threadId, std::move(ptr));//threads_.emplaceback(std::move(ptr));//启动线程threads[threadId]-start();//修改线程个数相关的变量curThreadSize;idleThreadSize;}//返回任务的Result对象return Result(sp);// return task-getResult(); }//开启线程池 void ThreadPool::start(int initThreadSize) {//设置线程池的运行状态isPoolRunningtrue;//记录初始线程个数initThreadSize initThreadSize;curThreadSize_ initThreadSize;//创建线程对象for (int i 0; i initThreadSize_; i){//创建thread线程对象的时候把线程函数给到thread线程对象auto ptr std::make_uniqueThread(std::bind(ThreadPool::threadFunc, this, std::placeholders::1));int threadId ptr-getId();threads.emplace(threadId, std::move(ptr));//threads_.emplace_back(std::move(ptr));//uniqueptr将左值引用的拷贝构造和赋值都delete了需要右值进行资源转移}//启动所有线程 std::vectorThread* threads;for (int i 0; i initThreadSize; i){threads[i]-start(); //需要去执行一个线程函数idleThreadSize_;//记录初始空闲线程的数量} }//定义线程函数 线程池的所有线程从任务队列里面消费任务 void ThreadPool::threadFunc(int threadid) //线程函数返回相应的线程也就结束了 {/std::cout begin threadFunc tid: std::this_thread::get_id() std::endl;std::cout end threadFunc tid: std::this_thread::get_id() std::endl;/auto lastTime std::chrono::high_resolutionclock().now();while (isPoolRunning){std::shared_ptrTask task;{//先获取锁std::uniquelockstd::mutex lock(taskQueMtx);std::cout tid: std::this_thread::get_id() 尝试获取任务… std::endl;//cached模式下有可能已经创建了很多的线程但是空闲时间超过60s,应该把多余的线程结束回收掉(超过initThreadSize数量的线程要进行回收)//当前时间-上一次线程执行的时间60s//每一秒中返回一次 怎么区分超时返回还是有任务待执行返回while (taskQue.size() 0){if (poolMode_ PoolMode::MODE_CACHED){//条件变量超时返回了if (std::cvstatus::timeout notEmpty.wait_for(lock, std::chrono::seconds(1))){auto now std::chrono::high_resolution_clock().now();auto dur std::chrono::duration_caststd::chrono::seconds(now - lastTime);if (dur.count() THREAD_MAX_IDLETIME curThreadSize initThreadSize){//开始回收当前线程//记录线程数量的相关变量的值修改//把线程对象从线程列表容器中删除 没有办法 threadFunc thread对象//threadidthread对象》删除threads.erase(threadid);// 这个id不是std::thisthread::getid() 是自己生成的我们自定义的curThreadSize–;idleThreadSize_–;std::cout threadid: std::this_thread::getid() exit! std::endl;return;}}}else{//等待notEmpty条件notEmpty.wait(lock);}//线程池结束回收线程资源if (!isPoolRunning){threads.erase(threadid);// 这个id不是std::this_thread::getid() 是自己生成的我们自定义的std::cout threadid: std::this_thread::getid() exit! std::endl;exitCond.notifyall();return;}}idleThreadSize–;//唤醒线程工作空闲线程-1std::cout tid: std::this_thread::getid() 获取任务成功… std::endl;//从任务队列中取一个任务出来task taskQue.front();taskQue.pop();taskSize–;//如果依然有剩余任务继续通知其它的线程执任务if (taskQue.size() 0){notEmpty.notifyall();}//取出一个任务进行通知通知可以继续提交生产任务notFull.notifyall();}//就应该把锁释放掉//当前线程负责执行这个任务if (task ! nullptr){//task-run();//执行任务把任务的返回值setVal方法给到Resulttask-exec();}idleThreadSize;//线程执行完任务空闲线程1lastTime std::chrono::high_resolutionclock().now();//更新线程执行完任务的时间}threads.erase(threadid);// 这个id不是std::this_thread::getid() 是自己生成的我们自定义的std::cout threadid: std::this_thread::getid() exit! std::endl;exitCond.notifyall(); }bool ThreadPool::checkRunningState() const {return isPoolRunning; }/// 线程方法实现 int Thread::generateId_ 0;//线程构造 Thread::Thread(ThreadFunc func):func(func),threadId(generateId) {}//线程析构 Thread::~Thread(){}//启动线程 void Thread::start() {//创建一个线程来执行一个线程函数std::thread t(func, threadId_);//C11来说 线程对象t 和线程函数func_t.detach();//设置分离线程线程对象t出作用域会析构但是线程函数不能结束否则程序会挂掉所以要将线程分离出去做到二者互不影响//pthread_detach pthread_t设置成分离线程//主线程要用pthreadjoin回收线程防止孤儿线程的出现} //获取线程id int Thread::getId()const {return threadId; }/// Task方法实现 Task::Task():result(nullptr) {}void Task::exec() {result-setVal(run());//这里发生多态调用 }void Task::setResult(Result* res) {result_ res; }/// Result方法的实现 Result::Result(std::sharedptrTask task, bool isValid):isValid(isValid),task(task) {task-setResult(this); }Any Result::get() // 用户调用的 {if (!isValid){return ;}//task任务如果没有执行完这里会阻塞用户的线程sem.wait();//用户调用get时如果任务在线程池中还没有被执行完那么调用get方法的线程就会阻塞住return std::move(any);//右值引用 }void Result::setVal(Any any)//谁调用的呢 {//存储task的返回值this-any std::move(any);sem.post();//已经获取的任务的返回值增加信号量资源 } 我们的资源回收代码如下 //线程池析构 ThreadPool::~ThreadPool() {isPoolRunning false;notEmpty_.notify_all();//等待线程池里面所有的线程返回 有两种状态阻塞 正在执行任务中std::uniquelockstd::mutex lock(taskQueMtx);exitCond.wait(lock, -bool {return threads.size() 0; }); } 现在有的线程没有被回收线程队列中还有线程所以就一直阻塞等待了。线程池的那个线程为什么没有被回收掉时而出现时而不出现的问题 我们通过在windows上调试 我们通过在Linux上进行gdb调试 主要通过gdb attach到正在运行的进程通过info threadsthread tidbt等命令查看各个线程的调用堆栈信息结合项目代码定位到发生死锁的代码片段分析死锁问题发生的原因 2.分析问题 原先针对上面的2种情况的处理方法如下 第3种情况有的线程执行完任务又进入while循环了 在这里有2种情况 1、pool线程先获取到锁线程池的线程获取不到锁阻塞。 此时pool线程看wait条件size0不满足条件就进入等待wait状态了并且把互斥锁mutex释放掉。 线程池的线程就获取到锁了发现任务队列没有任务了这个任务就在notEmpty条件变量上wait但是此时pool线程没有办法再对这个条件变量notify了。 发生死锁了 2、线程池里的线程先获取到锁发生任务队列为空在条件变量notEmpty上wait了释放锁然后pool线程抢到锁只是看exitCond条件变量的wait条件看size还是大于0还是死锁了。 解决方法pool线程获取到锁后再notify //线程池析构 ThreadPool::~ThreadPool() {isPoolRunning_ false;//等待线程池里面所有的线程返回 有两种状态阻塞 正在执行任务中std::uniquelockstd::mutex lock(taskQueMtx);notEmpty_.notifyall();exitCond.wait(lock, -bool {return threads_.size() 0; }); }我们在消费者线程进行锁双重判断 //定义线程函数 线程池的所有线程从任务队列里面消费任务 void ThreadPool::threadFunc(int threadid)//线程函数返回相应的线程也就结束了 {auto lastTime std::chrono::high_resolution_clock().now();//所有任务必须执行完成线程池才可以回收所有线程资源for (;;){std::shared_ptrTask task;{//先获取锁我们要注意控制锁的范围取完任务就释放锁std::uniquelockstd::mutex lock(taskQueMtx);std::cout tid: std::this_thread::get_id() 尝试获取任务… std::endl;//cached模式下有可能已经创建了很多的线程但是空闲时间超过60s应该把多余的线程//结束回收掉超过initThreadSize数量的线程要进行回收//当前时间 - 上一次线程执行的时间 60s//每一秒中返回一次 怎么区分超时返回还是有任务待执行返回//锁 双重判断while (taskQue.size() 0){//线程池要结束回收线程资源if (!isPoolRunning){threads.erase(threadid);//std::this_thread::getid()std::cout threadid: std::this_thread::getid() exit! std::endl;exitCond.notifyall();return;//线程函数结束线程结束}if (poolMode PoolMode::MODE_CACHED){//条件变量超时返回了if (std::cvstatus::timeout notEmpty.wait_for(lock, std::chrono::seconds(1))){auto now std::chrono::high_resolution_clock().now();auto dur std::chrono::duration_caststd::chrono::seconds(now - lastTime);if (dur.count() THREAD_MAX_IDLETIME curThreadSize initThreadSize)//任务数量大于空闲线程数量{//开始回收当前线程//记录线程数量的相关变量的值修改//把线程对象从线程列表容器中删除 没有办法 threadFunc《》thread对象//通过threadid thread对象 删除threads.erase(threadid);//std::thisthread::getid()curThreadSize–;idleThreadSize_–;std::cout threadid: std::this_thread::getid() exit! std::endl;return;}}}else{//等待notEmpty条件notEmpty.wait(lock);}//if (!isPoolRunning)//{// threads.erase(threadid);//std::this_thread::getid()// std::cout threadid: std::this_thread::getid() exit!// std::endl;// exitCond.notifyall();// return;//结束线程函数就是结束当前线程了!//}}idleThreadSize–;std::cout tid: std::this_thread::getid() 获取任务成功… std::endl;//从任务队列种取一个任务出来task taskQue.front();taskQue.pop();taskSize–;//如果依然有剩余任务继续通知其它得线程执行任务if (taskQue.size() 0){notEmpty.notifyall();}//取出一个任务进行通知通知可以继续提交生产任务notFull.notifyall();} //就应该把锁释放掉//当前线程负责执行这个任务if (task ! nullptr){//task-run();//执行任务把任务的返回值setVal方法给到Result基类指针调用派生类对象的同名覆盖方法task-exec();//用户还是使用run方法}idleThreadSize;lastTime std::chrono::high_resolution_clock().now();//更新线程执行完任务的时间} }