赞
踩
线程系列:
Linux–线程的认识(一)
Linux–线程的分离、线程库的地址关系的理解、线程的简单封装(二)
线程的互斥:临界资源只能在同一时间被一个线程使用
生产消费模型
信号量
线程池(包含日志的解释)
线程安全指的是在多线程环境下,某个操作或方法被多个线程并发执行时,能够保持数据的一致性和完整性,即不会因为多个线程的交替执行而导致数据被破坏或程序的行为不符合预期。
简单来说,如果一个操作在多线程环境下执行时,能够保证数据的一致性和操作的原子性,那么这个操作就是线程安全的。
死锁是指两个或多个进程(线程)在执行过程中,因竞争资源或由于彼此通信而造成的一种阻塞现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程(线程)称为死锁进程。
在计算机系统中,对于每种资源都设置一个最大需求量和当前可用量。当一个进程提出资源请求时,系统首先检查该进程是否满足其最大需求量限制,如果请求合法,则尝试分配资源给该进程并检查是否会导致系统进入不安全状态(即可能发生死锁),如果不会,则分配资源;否则,拒绝该进程的请求。
1.检查请求是否合法:
2.模拟分配资源:
3.执行安全性算法:
安全性算法用于检查此次资源分配后,系统是否处于安全状态。具体步骤如下:
4.根据检查结果决定是否真正分配资源:
在上一篇中,我们使用的线程池是可以无限制的创建的,如果每个任务或请求都创建一个新的线程池,那么当任务或请求量很大时,会导致创建大量的线程池实例,每个实例内部又可能包含多个线程,这将极大地浪费系统资源,包括内存和CPU时间。
使用单例模式可以确保整个应用或系统只存在一个线程池实例,这样所有的任务或请求都可以共享这个线程池中的线程,避免了资源的浪费;
#pragma once #include<iostream> #include<vector> #include<queue> #include<pthread.h> #include"Thread.hpp" #include"Log.hpp" #include"LockGuard.hpp" using namespace ThreadMdule; using namespace std; const static int gdefaultthreadnum=3;//默认线程池的线程数 template <class T> class ThreadPool { public: ThreadPool(int threadnum=gdefaultthreadnum) :_threadnum(threadnum),_waitnum(0),_isrunning(false) { pthread_mutex_init(&_mutex,nullptr); pthread_cond_init(&_cond,nullptr); LOG(INFO,"ThreadPool COnstruct."); } //禁用拷贝赋值 ThreadPool(const ThreadPool<T>&) = delete; ThreadPool<T>& operator=(const ThreadPool<T>&) = delete; //单例:懒汉模式 static ThreadPool<T>* GetInstance() { //再次判断,减少获取单例的加锁成本,保证线程安全 if(_instance==nullptr) { LockGuard lockguard(&_lock); if(_instance==nullptr) { _instance= new ThreadPool<T>(); _instance->InitThreadPool(); _instance->Start(); LOG(DEBUG,"创建单例线程池"); return _instance; } } LOG(DEBUG,"获取单例线程池"); return _instance; } //各个线程独立的任务函数 void HandlerTask(string name) { LOG(INFO,"%s is running...",name.c_str()); while(true) { LockQueue();//开启保护 //等到有任务时才退出循环执行下列语句 while(_task_queue.empty()&&_isrunning) { _waitnum++; ThreadSleep(); _waitnum--; } //当任务队列空并且线程池停止时线程退出 if(_task_queue.empty()&&!_isrunning) { UnlockQueue(); cout<<name<<" quit "<<endl; sleep(1); break; } //1.任务队列不为空&&线程池开启 //2.任务队列不为空&&线程池关闭,直到任务队列为空 //所以,只要有任务,就要处理任务 T t=_task_queue.front();//取出对应任务 _task_queue.pop(); UnlockQueue(); LOG(DEBUG,"%s get a task",name.c_str()); //处理任务 t(); LOG(DEBUG,"%s handler a task,result is: %s",name.c_str(),t.ResultToString().c_str()); } } //线程池中线程的构建 void InitThreadPool() { for(int i=0;i<_threadnum;i++) { string name="thread-"+to_string(i+1); _threads.emplace_back(bind(&ThreadPool::HandlerTask,this,placeholders::_1),name); LOG(INFO,"init thread %s done",name.c_str()); } _isrunning=true; } //线程池的启动 void Start() { for(auto& thread:_threads) { thread.start(); } } //线程池停止 void Stop() { LockQueue(); _isrunning=false; ThreadWakeupAll(); UnlockQueue(); } void Wait() { for(auto& thread:_threads) { thread.Join(); LOG(INFO,"%s is quit...",thread.name().c_str()); } } //将任务入队列 bool Enqueue(const T& t) { bool ret=false; LockQueue(); if(_isrunning) { _task_queue.push(t); //如果有空闲的线程,那么唤醒线程让其执行任务 if(_waitnum>0) { ThreadWakeup(); } LOG(DEBUG,"enqueue task success"); ret=true; } UnlockQueue(); return ret; } ~ThreadPool() { pthread_mutex_destroy(&_mutex); pthread_cond_destroy(&_cond); } private: void LockQueue() { pthread_mutex_lock(&_mutex); } void UnlockQueue() { pthread_mutex_unlock(&_mutex); } void ThreadSleep() { pthread_cond_wait(&_cond, &_mutex); } void ThreadWakeup() { pthread_cond_signal(&_cond); } void ThreadWakeupAll() { pthread_cond_broadcast(&_cond); } int _threadnum;//线程数 vector<Thread> _threads;//存储线程的vector queue<T> _task_queue;//输入的任务队列 pthread_mutex_t _mutex;//互斥锁 pthread_cond_t _cond;//条件变量 int _waitnum;//空闲的线程数 bool _isrunning;//表示线程池是否启动 //单例模式 static ThreadPool<T>* _instance; static pthread_mutex_t _lock; }; template<typename T> ThreadPool<T>* ThreadPool<T>::_instance=nullptr; template<typename T> pthread_mutex_t ThreadPool<T>::_lock = PTHREAD_MUTEX_INITIALIZER;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。