单例模式的线程安全
需要双重判空指针,降低锁冲突的概率,提高性能原因1: 当第一次实例化单例时,可能有多个线程同时到来,并且svr指针为空这时他们就会去竞争锁,但只有一个线程会最快拿到锁,并且成功实例化出单例对象但此时如果不加双重判空指针,那些也进了第一层if判断的,仍然会去实例化出对象 原因2: 为了线程安全,必然要加锁,加锁之后再去判空但每次调用GetInstance()
都需要去获得锁,释放锁,效率低下此时再加一层外层if判空,这样就会避免后续调用GetInstance()
时没必要的锁竞争 static void *ThreadRoutine(void *args)
为什么要设置为static方法?
pthread_create
传递给线程的方法只能是返回值为void*
,参数为void*
的函数static将函数方法声明为静态方法,此时该方法没有隐含的this指针,就可以在类内把这个方法传递给线程调用了int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
while()防止伪唤醒
可能条件变量唤醒线程时,有多个线程同时被唤醒,但是只有一个最快的线程PopTask()
可以拿到任务,此时其他线程就会出错while()可以在被唤醒的情况下,再次判断任务队列是否有任务这样可以保证,在某个线程醒来的时候,一定是占有互斥锁的 static const int THREAD_POOL_NUM = 10;// 单例模式class ThreadPool{public: static ThreadPool *GetInstance(int num = THREAD_POOL_NUM) { static pthread_mutex_t sMtx = PTHREAD_MUTEX_INITIALIZER; if (_tp == nullptr) { pthread_mutex_lock(&sMtx); if (_tp == nullptr) // 双重判断,以防线程安全问题 { _tp = new ThreadPool(num); _tp->Init(); } pthread_mutex_unlock(&sMtx); } return _tp; } // static使该成员函数没有this指针,因为线程执行的函数只能有一个void*参数 static void *ThreadRoutine(void *args) { ThreadPool *tp = (ThreadPool *)args; while(true) { Task task; tp->Lock(); while(tp->TaskQueueIsEmpty()) // while防止伪唤醒 { tp->ThreadWait(); } tp->Pop(task); tp->Unlock(); // 注意,不要在临界资源区内处理任务哦~ task.ProcessOn(); } } bool Init() { for (int i = 0; i < _num; i++) { pthread_t tid; if (pthread_create(&tid, nullptr, ThreadRoutine, this) != 0) { LOG(FATAL, "Create ThreadPool Error"); return false; } } LOG(INFO, "Create ThreadPool Success"); return true; } void Push(const Task& task) // in { Lock(); _taskQueue.push(task); // 任务队列为临界资源,操作要加锁 Unlock(); ThreadWakeUp(); } void Pop(Task& task) // out { task = _taskQueue.front(); _taskQueue.pop(); } void ThreadWait() { pthread_cond_wait(&_cond, &_mtx); } void ThreadWakeUp() { pthread_cond_signal(&_cond); } bool TaskQueueIsEmpty() { return !_taskQueue.size(); } void Lock() { pthread_mutex_lock(&_mtx); } void Unlock() { pthread_mutex_unlock(&_mtx); } bool IsStop() { return _stop; } ~ThreadPool() { pthread_mutex_destroy(&_mtx); pthread_cond_destroy(&_cond); }private: ThreadPool(int num = THREAD_POOL_NUM) : _num(num), _stop(false) { pthread_mutex_init(&_mtx, nullptr); pthread_cond_init(&_cond, nullptr); } ThreadPool(const ThreadPool &) = delete;private: int _num; bool _stop; std::queue<Task> _taskQueue; pthread_mutex_t _mtx; pthread_cond_t _cond; static ThreadPool *_tp;};ThreadPool* ThreadPool::_tp = nullptr;