并发
两个或多个独立的活动同时发生。
计算机领域的并发
并发:单个系统里同时执行多个独立的任务。
对于只有一个处理器的计算机:同一时刻只能执行一个任务,当它在多个任务切换执行时,可以看成多个并行任务在执行,仍然称为并发。
对于多核计算机:可以真正做到任务同时执行,称为硬件并发。
并发的途径
-
多进程并发:将应用程序分为多个独立的进程。
-
优点:操作系统在进程间提供附加的保护操作和更高级别的通信机制,意味着可以更容易编写安全的并发代码;可以使用远程连接(可能需要联网)的方式,在不同的机器上运行独立的进程。
-
缺点:速度慢,这是因为操作系统会在进程间提供了一定的保护措施,以避免一个进程去修改另一个进程的数据 ;运行多个进程所需的固定开销:需要时间启动进程,操作系统需要内部资源来管理进程。
-
多线程并发:单个进程中运行多个线程。
优点:进程中的所有线程都共享地址空间,并且所有线程访问到大部分数据———全局变量仍然是全局的,指针、对象的引用或数据可以在线程之间传递。地址空间共享,以及缺少线程间数据的保护,使得操作系统的记录工作量减小,所以使用多线程相关的开销远远小于使用多个进程。多个单线程/进程间的通信(包含启动)要比单一进程中的多线程间的通信(包括启动)的开销大
缺点:共享内存的灵活性是有代价的:如果数据要被多个线程访问,那么程序员必须确保每个线程所访问到的数据是一致的,在编写代码时适当地注意即可,这同样也意味着需要对线程通信做大量的工作。
为什么要使用并发
主要原因:关注点分离和性能。
关注点分离
通过将相关的代码与无关的代码分离,每个线程执行自己的任务,可以使程序更容易理解和测试,从而减少出错的可能性。若不显式地使用并发,就得编写一个任务切换框架,或者在操作中主动地调用一段不相关的代码。
提高性能
两种方式利用并发提高性能:第一,将一个单个任务分成几部分,且各自并行运行,从而降低总运行时间。这就是任务并行( task parallelism)
第二种方法是使用可并行的方式,来解决更大的问题;与其同时处理一个文件,不如酌情处理2个、10个或20个。
什么时候不使用并发
- 不使用并发的唯一原因就是,收益比不上成本。除非潜在的性能增益足够大或关注点分离地足够清晰,能抵消所需的额外的开发时间以及与维护多线程代码相关的额外成本(代码正确的前提下);否则,别用并发。
- 同样地,性能增益可能会小于预期;因为操作系统需要分配内核相关资源和堆栈空间,所以在启动线程时存在固有的开销,然后才能把新线程加入调度器中,所有这一切都需要时间。
- 此外,线程是有限的资源。如果让太多的线程同时运行,则会消耗很多操作系统资源,从而使得操作系统整体上运行得更加缓慢。因为每个线程都需要一个独立的堆栈空间,所以运行太多的线程也会耗尽进程的可用内存或地址空间
- 最后,运行越多的线程,操作系统就需要做越多的上下文切换
C++并发性能
虽然C++线程库为多线程和并发处理提供了较全面的工具,但在某些平台上提供额外的工具。为了方便地访问那些工具的同时,又使用标准C++线程库,在C++线程库中提供一个 native_handle() 成员函数,允许通过使用平台相关API直接操作底层实现。
一个简单的C++多线程程序
#include <iostream>
#include <thread>
using namespace std;
void hello()
{
cout << "hello concurrent world" << endl;
}
int main()
{
thread t(hello); //启动一个新线程,执行hello
t.join();
return 0;
}