在C++11之前,语言本身和C++标准并不支持并发,虽然编译器可以实现并对此提供某种支持。但在C++11中,不论是内核语言还是标准库都加强支持并发编程。
以下内容适用于内核语言:
*如今具备了这样一个内存模型,保证当你修改“被不同的两个线程使用的”两个不同对象时,它们彼此独立。在C++11之前,并不保证“某一线程涂写一个 char “不会干涉”另一线程涂写另一个char“。
*引入一个新关键字 thread_local,用来定义”线程特定“的变量和对象。
标准库提供以下特性:
*若干线程安全相关的保证。
*支持类和函数的并发运算(启动和同步多个线程)。
C++标准库提供的一般性并发保证:
自C++11起,C++标准库对于并发和多线程提供的一般性规范如下:
*一般而言,多个线程共享同一个程序库对象而其中至少一个线程改动该对象时,可能会导致不明确的行为。面对被多线程共享的某个标准库类型的,某个对象时,改动它会导致出现 ”不明确行为“的风险。除非该类型被明确指定为 ”无数据竞争的共享“或使用者为其提供一个 ” locking(加锁)“机制。
*对于,某个线程的对象构造期间,另一个线程使用了该对象,仍会导致不明确行为。同样的道理,在某个线程中析构对象,而另一个线程正在使用它,也会导致不明确的行为。对于这样的行为,甚至也适用于针对线程同步而提供的对象。
”并发访问标准库对象“的几个最重要的地方是:
*STL容器和容器适配器提供以下保证:
——并发的只读访问是允许的。这明确意味着调用 nonconstant 成员函数 begin() ,end(),rbegin(),rend(),front(),back(),data(),find(),lower_bound(),upper_bound(),equal_range(),at(), operator[](关联式容器除外),以及通过迭代器进行的访问(只要它们不改动容器),都是允许的。
——并发处理同一容器内的不同元素是可以的(除 class vector<bool>)。因此,不同的线程可以并发的 读、写、读写 相同元素内的不同元素。例如,每个线程都可以对一个可共享的 vector 处理某些东西并将结果储存于起元素中。
*”对标准 stream 进行格式化输入和输出“的并发处理是可能的,但是那样可能会导致 字符插叙,这种输入输出默认适用 std::cin、std::cout、和 std::cerr。然而对于 string stream、file stream 或 streambuffer,并发处理坑能导致不明确行为。
*atexit()和at_quick_exit()的并发调用时同步的。相同情况适用于那些设定取得 new、terminate或unexpected handler的函数,此外,getenv()也是同步调用的。
*默认分配器的所有成员,除了析构函数,其并发处理都被同步。
C++标准库保证它不存在任何隐形的副作用会破坏”对不同对象的并发处理“。因此,C++标准库:
*不会去访问那些 reachable object ,除非某个操作特别指定要那些东西。
*不被允许在其内部引入 shared static object 却未令其同步。
*唯有在”对程序不存在可见副作用“的情况下才允许编译器将操作并行。