第一章
Why use concurrency,There are two main reasons to use concurrency in an application: separation of con-cerns and performance.(这句写得很精辟:)
我:分离实现逻辑,然后使用“状态迁移表”这种消息驱动的方式,用在APP的设计上非常的方便。
什么时候不要使用concurrency?
使用线程是有代价的,因为线程需要占资源(stack),context switch。还有,多线程比单线程的程序更难理解,更容易出错。要权衡所得与所失。
C++中的多线程:
C++98的时候,没有多线程,主要是使用系统API,或是第三方线程库(Boost,MFC,ACE)等。最大的问题是:C++ 本身没有多线程的内存模型。特别是在想写高性能,跨平台的多线程程序时,各个编译器和平台之间不同的表现会带来一些问题。
C++11标准中加入了多线程的内存模型以及标准库有了一套线程和同步相关的库。
C++11线程库的性能:
我:这大概是C/C++程序员最为关心的问题之一吧……(一般比易用性看得重……)
标准库的设计目标是“在实现抽象的时候,相比起底层次的调用来说,没有,或是几乎没有性能损失”
作者认为:程序员几乎不会因为使用标准的线程库代替原来的多线程库而出现性能的瓶颈。某些线程库特性的实现上会稍微有一些性能损失。但是对程序来说无关紧要。作者认为,就算profile的时候性能瓶颈出现在线程库上(比如说同步锁上),那么应该优化的一般也是程序的设计(框架或是结构),而不是用其它的实现来代替标准的线程库。
第二章 : 线程的基本操作
最重要的库:std::thread 头文件 <thread>
void do_some_work(); std::thread my_thread(do_some_work);
或是函数对象也可以:
class background_task { public: void operator()() const { do_something(); do_something_else(); } }; background_task f; std::thread my_thread(f);
注意:
std::thread my_thread(background_task());
这种写法是不行的,因为编译器会以为你在声明一个函数,名字叫my_thread,一个参数一个返回值(std::thread)
如果确实想用临时变量生成一个thread,那么可以用下面两个方法之一:
std::thread my_thread((background_task()));
std::thread my_thread{background_task()};
或是lambda表达式:
std::thread my_thread([](
do_something();
do_something_else();
});
注意线程的生存期问题,注意不要让线程访问已经失效的对象。
Listing2.1 有个入门的例子
2.1.3 和 2.1.4
join函数和detach函数
join让你等一个线程的结束
detach让一个线程在后台运行。(detach之后就不能再join它了)
在生成一个线程对象后,你必须调用两者中的一个,否则,在std::thread的析构函数中,会terminate整个program~!??
Try it!~
2.2 在创建线程的时候给线程函数传参数
void f(int i,std::string const& s); std::thread t(f, 3,”hello”);
传递参数的方法非常简单,只需要在thread对象的构造函数中,第二个参考起依次按线程函数(或是函数对象)的参数列表传递参数即可。
但这里作者指出了几种可能出现的“误解”,原因都是,std::thread的构造函数的参数与线程函数的参数不会完全一致,因此,在implicite convert和pass by reference时很可能发生“错误”。另外也要注意传入参数的“生命周期”。(参考bind)
(这一节需要再读!)
2.3 传递线程对象
many resource-owning types in the C++ Standard Library such as std::ifstreamand std::unique_ptrare movablebut not copyable, and std::thread is one of them.
std::thread 支持 move, 可以放在容器中。
2.4
std::thread::hardware_concurrency()
返回所运行的平台的真正的“可并行数”。但是也可能为 0
这个函数用于使程序有能力在运行期获取平台的并行能力并选用相应的策略。
2.5
thread_id 用于标识线程