这本书确实是学习多核时代采用现代C++编写多线程程序的好书,下面是学习总结:
第一章 线程安全的对象生命期管理
对象的创建很简单,但是不要在构造期间泄漏this指针,比如不要在构造函数中注册任何回调函数,二段式构造有时候是好方法。
对象的销毁及析构在多线程中太难,一个万能的解决方案是引入另外一层间接性,比如C++11中的一对神兵利器shared_ptr/week_ptr;
shared_ptr能实现线程安全的对象释放,但是它本身不是100%线程安全的,如果要多个线程同时读写,需要加锁。
线程安全的Observer分析及解决方案;对象池Factory,使用shared_ptr定制析构功能,以及弱回调解决生命期问题;
RAII(资源获取即初始化)是C++语言区别于其它所有编程语言的最重要的特性;一个不懂RAII的C++程序员不是一个合格的程序员。
第二章 线程同步精要
四项原则:
首要原则是尽量最低限度的共享对象;
其次是使用高级的并发编程构件:如TaskQueue, Produce-Consumer Queue, CountDownLatch;
底层同步原语只使用非递归的互斥器和条件变量,慎用读写锁,不要用信号量;
除了使用atomic整数之外,不自觉编写lock-free代码;
作者的个人原则:
用RAII手法封装mutex的创建,销毁,加锁,解锁这4个操作;
只用非递归的mutex;
不手工调用lock()和unlock()函数;
不使用跨进程的mutex,进程间通信只用TCP sockets;
函数拆分重构,如果一个函数既可能在已经加锁的情况下调用,又可能在未加锁的情况下调用,那么就拆分成两个函数。
线程安全的Singleton实现,使用pthread_once。
第3章 多线程服务器的适用场合
多线程服务器程序中的线程大致可分为3类:
IO线程;
计算线程;
第三方库所用的线程;
BlockingQueue是构建多线程程序的利器;
第4章 C++多线程系统编程精要
C++系统库的线程安全性,关键是规定内存模型。
编写线程安全程序的一个难点在于线程安全是不可组合的,比如一个函数调用了2个线程安全的函数,结果不一定是线程安全的。
线程的创建比销毁容易的多,简单的准则:
程序库不应该在未提前告知的情况下创建自己的“背景线程”;
尽量用相同的方式创建线程;
在进入main()函数之前不应该启动线程;
线程的创建最好能在初始化阶段全部完成;
线程的销毁有几种方式:
自然死亡。这是线程正常退出的方式。
非正常死亡。抛出异常,或者触发信号等非法操作;
自杀。调用pthread_exit()来退出。
他杀。调用pthread_candel()来强制终止某个线程。
Muduo::Thread不是传统意义上的RAII,因为它析构的时候没有销毁持有的Pthreads线程句柄;一般而言,我们会让Thre::ad对象的生命周期长于线程,然后通过Thread::join()来等待线程结束并释放线程资源。
多线程与IO,每个文件描述符只由一个线程操作。
用RAII包装文件描述符。
RAII与fork,子进程不一定正常工作。fork一般不能在多线程程序中调用。
唯一安全的做法是在fork之后立即调用exec()执行另一个程序,隔断子进程与父进程的联系。