前面学了 C的基本概念,由于并发编程内容比较多,这里单独学习《C Concurrency In Action - second Edition 2019》并发编程
问题 1:什么是并发
在一个双核机器(具有两个处理核心)上,每个任务可以在各自的处理核心上执行。在单核机器上做任务切换时,每个任务的块交织进行。单核交织进行任务的时候中间有一小段分隔(任务切换也是需要时间的)
为了实现交织进行,系统每次从一个任务切换到另一个时都需要切换一次上下文(context switch),进行上下文的切换时,操作系统必须为当前运行的任务保存CPU的状态和指令指针,并计算出要切换到哪个任务,并为即将切换到的任务重新加载处理器状态。然后,CPU可能要将新任务的指令和数据的内存载入到缓存中,这会阻止CPU执行任何指令,从而造成的更多的延迟。

问题 2:如何实施并发
- 第一种,每个进程只要一个线程,同时运行多个进程。进程中的所有线程共享地址空间,需要保证数据一致性
- 第二种,每个进程有多个线程。独立进程可以通过进程间常规的通信方式(信号、套接字、文件、管道)。缺点是 相比线程间通信,它的速度慢,每个进程所需的固定开销(时间启动、内部资源管理进程)。但是编码更容易切安全
问题 3:什么时候不用并发
不使用并发的唯一原因就是收益比不上成本。使用并发的代码在很多情况下难以理解,因此编写和维护的多线程代码就会直接产生脑力成本,同时额外的复杂性也可能引起更多的错误。
例子
1 |
|
与启动一个独立的线程
1 |
|
序号说明:
- 标准C++库中对多线程支持的声明在新的头文件中
- 每个线程都必须具有一个初始函数(
initial function
),新线程的执行从此开始。对于应用程序来说,初始线程是main()
,对于其他线程,可以在std::thread
对象的构造函数中指定 - 初始线程拉起新线程之后,会同时继续执行。如果不等待新线程结束,就将自顾自地继续运行到
main()
的结束,有可能发生在新线程运行之前。所以调用join()
的等待新线程结束
这里包含了一些问题,待后续解答
- 进程与线程有什么区别
- 创建线程的时候发生了什么
- 线程是如何管理的
- 线程是如何通信的
参考链接
- 《C++ Concurrency In Action - second Edition 2019》