当前位置: 首页 > Linux

多线程服务器编程[2]——线程同步精要

时间:2023-04-06 18:30:00 Linux

线程同步的四个原则最少共享对象以减少对同步的需要使用高级并发组件,例如TaskQueue、Producer-ConsumerQueue、CountDownLatch等。在万不得已的情况下使用低级同步原语时,只使用非-recursivemutexes和conditionvariables,谨慎使用读写锁,不要使用信号量除了使用原子整数,不要自己写无锁代码,也不要使用内核级同步原语互斥量(mutex)使用原理RAII对mutex的创建、销毁、加锁、解锁进行封装,保证锁的有效期等于一个作用域(ScopedLocking),有助于死锁发生时的定位。保证不会手动调用lock和unlock。保证不跨进程跨线程调用锁。不要忘记反复解锁和锁定。仅使用非递归互斥锁(即不可重入互斥锁)。每次构造Guard对象时,想一想一路上已经持有的锁(函数调用栈),防止锁的顺序不同导致的锁。为什么死锁只使用非递归互斥?同一个线程可以重复加锁递归互斥量,但不能重复加锁非递归互斥量。在同一个县内多次加锁非递归互斥量会造成两次死锁。后者的性能差别不大。非递归锁可以提前暴露编程问题。除了线程间的死锁,单个线程也会导致死锁。当保证使用ScopedLocking时,可以通过分析调用栈来获取原因。条件变量使用条件变量实现BlockingQueuemuduo::MutexLockmutex;muduo::Conditioncond(mutex);std::dequequeue;intdequeue(){MutexLockGuardlock(mutex);while(queue.empty()){cond.wait();//解锁互斥并等待(原子地)}assert(!queue.empty());inttop=queue.front();queue.pop_front();returntop;}voidenqueue(intx){{MutexLockGuard锁(mutex);队列。推回(x);}条件。通知();//wakeupthewaitside}每次添加时调用notify(),而不是notifyall()以避免雷电效应。不仅notify()when0->1,每次添加通知时,当有多个consumers时,可以高效唤醒,否则只会唤醒一个,见https://book.douban.com/annot...使用条件变量实现CountDownLatch(倒计时)classCountDownLatch:boost::noncopyable{public:explicitCountDownLatch(intcount);无效等待();无效倒计时();私有的:可变的MutexLockmutex_;条件条件_;intcount_;}voidCountDownLatch::wait(){MutexLockGuard锁(mutex_);0){条件_.等待();}}voidCountDownLatch::countDown(){MutexLockGuard锁(mutex_);-数数_;if(count_==0){condition_.notifyAll();}}封装MutexLock、MutexLockGuard、Condition实现类MutexLock:boost::noncopyable{public:MutexLock():holder_(0){pthread_mutex_init(&mutex_NULL);}~MutexLock(){assert(hoilder_==0);pthread_mutex_destory(&互斥量);}boolisLockedByThisThread(){returnholder_==CurrentThread::tid();}voidassertLocked(){assert(isLockedByThisThread());}voidlock(){pthread_mutex_lock(&mutex);holder_=CurrentThread::tid();}voidunlock(){holder_=0;pthread_mutex_unlock();}pthread_mutex_t*getPthreadMutex(){返回&mutex;}私有:pthread_mutex_tmutex_;pid_t持有人_;}classMutexLockGuard:boost::noncopyable{public:explicitMutexLockGuard(MutexLock&mutex):mutex_(mutex){mutex_.lock();}~MutexLockGuard(){mutex_.unlock;}private:MutexLock&mutex_;}#defineMutexLockGuard(x)static_assert(false,"Missingmutexguardvariablename!")classCondition:boost::noncopyable{public:explicitCondition(MutexLock&mutex):mutex_(mutex){pthread_cond_init(&pcond_,NULL);}~Condition(){pthread_cond_destory(&pcond_);}voidwait(){pthread_cond_wait(&pcond_,mutex_.getPthreadMutex));}voidnotify(){pthread_cond_signal(&pcond_);}voidnotifyAll(){pthread_cond_boardcast(&pcond);}private:MutexLock&mutex_;pthread_cond_tpcond_;任务,使用通用互斥锁和条件变量,使用RAII技术和ScoopedLocking