6.3 原子类型与原子操作

类别:所有人

6.3.1 并行编程、多线程与C++11

在C++11之前,C/C++一直是一种顺序的编程语言。顺序是指所有指令都是串行执行的,即在相同的时刻,有且仅有单个CPU的程序计数器指向可执行代码的代码段,并运行代码段中的指令。而C/C++代码也总是对应地拥有一份操作系统赋予进程的包括堆、栈、可执行的(代码)及不可执行的(数据)在内的各种内存区域。

不过随着处理器的发展,半导体工业在提升处理器频率时遭遇到漏电流等各种技术瓶颈。以顺序执行编程模型为基础的单核处理器的发展,在高速发展20多年后开始接近停滞。随之而来的是多核处理器的发展风潮。相应地,编程语言逐渐也开始向并行化的编程方式发展。

常见的并行编程有多种模型,如共享内存、多线程、消息传递等。不过从实用性上讲,多线程模型往往具有较大的优势。多线程模型允许同一时间有多个处理器单元执行统一进程中的代码部分,而通过分离的栈空间和共享的数据区及堆栈空间,线程可以拥有独立的执行状态以及进行快速的数据共享。因此在2000年以后,主流的芯片厂商以及编译器开发厂商或组织都开始推广适用于多核处理器的多线程编程模型。而编程语言,也逐渐地将线程模型纳入语言特性或者语言库中。不过C/C++由于新标准迟迟未出,因此我们也就一直没有看到集成于C/C++语言特性中的线程特性或者线程库。

在C++11之前,在C/C++中程序中使用线程却并非鲜见。这样的代码主要使用POSIX线程(Pthread)和OpenMP编译器指令两种编程模型来完成程序的线程化。其中,POSIX线程是POSIX标准中关于线程的部分,程序员可以通过一些Pthread线程的API来完成线程的创建、数据的共享、同步等功能。Pthread主要用于C语言,在类UNIX系统上,如FreeBSD、NetBSD、OpenBSD、GNU/Linux、Mac OS X,甚至是Windows上都有实现(Windows上Pthread的实现并非“原生”,主要还是包装为Windows的线程库)。不过在使用的便利性上,Pthread不如后来者OpenMP。OpenMP的编译器指令将大部分的线程化的工作交给了编译器完成,而将识别需要线程化的区域的工作交给了程序员,这样的使用方式非常简单,也易于推广。因此,OpenMP得到了业界大多数主流软硬件厂商,如AMD、IBM、Intel、Cray、HP、Fujitsu、Nvidia、NEC、Microsoft、Texas Instruments、Oracle Corporation等的支持。除去C/C++语言外,OpenMP还可以用于Fortran语言,是现行的一种非常有影响力的使用线程程序优化的编程模型。

而在C++11中,标准的一个相当大的变化就是引入了多线程的支持。这使得C/C++语言在进行线程编程时,不必依赖第三方库和标准。而C/C++对线程的支持,一个最为重要的部分,就是在原子操作中引入了原子类型的概念。