C11 对整型变量原子操作的支持在 C 98/03 标准中如果想对整型变量进行原子操作要么利用操作系统提供的相关原子操作 API要么利用对应操作系统提供的锁对象来对变量进行保护无论是哪种方式编写的代码都无法实现跨平台操作例如上一小介绍的Interlocked系列 API 代码仅能运行于 Windows 系统无法移植到 Linux 系统。C 11 新标准发布以后改变了这种困境新标准提供了对整型变量原子操作的相关库即 std::atomic 这是一个模板类型templateclass T struct atomic;你可以传入具体的整型类型如bool、char、short、int、uint等对模板进行实例化实际上 stl 库也提供了这些实例化的模板类型类型别名定义std::atomic_boolstd::atomicboolstd::atomic_charstd::atomiccharstd::atomic_scharstd::atomicsigned charstd::atomic_ucharstd::atomicunsigned charstd::atomic_shortstd::atomicshortstd::atomic_ushortstd::atomicunsigned shortstd::atomic_intstd::atomicintstd::atomic_uintstd::atomicunsigned intstd::atomic_longstd::atomiclongstd::atomic_ulongstd::atomicunsigned longstd::atomic_llongstd::atomiclong longstd::atomic_ullongstd::atomicunsigned long longstd::atomic_char16_tstd::atomicchar16_tstd::atomic_char32_tstd::atomicchar32_tstd::atomic_wchar_tstd::atomicwchar_tstd::atomic_int8_tstd::atomicstd::int8_tstd::atomic_uint8_tstd::atomicstd::uint8_tstd::atomic_int16_tstd::atomicstd::int16_tstd::atomic_uint16_tstd::atomicstd::uint16_tstd::atomic_int32_tstd::atomicstd::int32_tstd::atomic_uint32_tstd::atomicstd::uint32_tstd::atomic_int64_tstd::atomicstd::int64_tstd::atomic_uint64_tstd::atomicstd::uint64_t上表中仅列出了 C11 支持的常用的整型原子变量完整的列表读者可以参考这里std::atomic - cppreference.com。有了 C 语言本身对原子变量的支持以后我们就可以“愉快地”写出跨平台的代码了我们来看一段代码#include atomic #include stdio.h int main() { std::atomicint value; value 99; printf(%d\n, (int)value); //自增1原子操作 value; printf(%d\n, (int)value); return 0; }以上代码可以同时在 Windows 和 Linux 平台上运行但是有读者可能会根据个人习惯将上述代码写成如下形式#include atomic #include stdio.h int main() { std::atomicint value 99; printf(%d\n, (int)value); //自增1原子操作 value; printf(%d\n, (int)value); return 0; }代码仅仅做了一点简单的改动这段代码在 Windows 平台上运行良好但是在 Linux 平台上会无法编译通过这里指的是在支持 C 11语法的 g 编译中编译提示错误是error: use of deleted function ‘std::atomicint::atomic(const std::atomicint)’产生这个错误的原因是 “std::atomicint value 99;” 这一行代码调用的是 std::atomic 的拷贝构造函数对于 int 型其形式一般如下std::atomicint::atomic(const std::atomicint rhs);而根据 C 11 的规范这个拷贝构造函数是默认使用delete语法禁止编译器生成的g 遵循了这个标准参见这里 https://zh.cppreference.com/w/cpp/atomic/atomic/operatoratomic operator( const atomic ) delete;所以 Linux 平台上编译器会提示错误而 Windows 的 VC 编译器没有遵循这个规范。而对于代码value 99;g 和 VC 同时实现规范中的T operator( T desired )因此如果读者想利用 C 11 提供的 std::atomic 库编写跨平台的代码在使用 std::atomic 提供的方法时建议参考官方 std::atomic 提供的接口说明来使用而不是想当然地认为一个方法在此平台上可以运行在另外一个平台也能有相同的行为避免出现上面说的这种情形。上述代码中之所以可以对 value 进行自增操作是因为std::atomic类内部重载了operator 运算符除此以外std::atomic提供了大量有用的方法这些方法您一定会觉得似曾相似方法名方法说明operator存储值于原子对象store原子地以非原子对象替换原子对象的值load原子地获得原子对象的值exchange原子地替换原子对象的值并获得它先前持有的值compare_exchange_weakcompare_exchange_strong原子地比较原子对象与非原子参数的值若相等则进行交换若不相等则进行加载fetch_add原子地将参数加到存储于原子对象的值并返回先前保有的值fetch_sub原子地从存储于原子对象的值减去参数并获得先前保有的值fetch_and原子地进行参数和原子对象的值的逐位与并获得先前保有的值fetch_or原子地进行参数和原子对象的值的逐位或并获得先前保有的值fetch_xor原子地进行参数和原子对象的值的逐位异或并获得先前保有的值operatoroperator(int)operator--operator--(int)令原子值增加或减少一operatoroperator-operatoroperator|operator^加、减或与原子值进行逐位与、或、异或