5.2.6 std::atomic<>主要类的模板

5.2.6 std::atomic<>主要类的模板

主模板的存在,在除了标准原子类型之外,允许用户使用自定义类型创建一个原子变量。不 是任何自定义类型都可以使用std::atomic<> 的:需要满足一定的标准才行。为了使用 std::atomic<UDT> (UDT是用户定义类型),这个类型必须有拷贝赋值运算符这就意味着这个类型不能有任何虚函数或虚基类,以及必须使用编译器创建的拷贝赋值操作。不仅仅是这 些,自定义类型中所有的基类和非静态数据成员也都需要支持拷贝赋值操作。这(基本上)就允 许编译器使用memcpy(),或赋值操作的等价操作,因为它们的实现中没有用户代码。

最后,这个类型必须是“位可比的”(bitwise equality comparable)。这与对赋值的要求差不多; 你不仅需要确定,一个UDT类型对象可以使用memcpy()进行拷贝,还要确定其对象可以使用 memcmp()对位进行比较之所以要求这么多,是为了保证比较/交换操作能正常的工作

以上严格的限制都是依据第3章中的一个建议:不要将锁定区域内的数据,以引用或指针的形 式,作为参数传递给用户提供的函数。通常情况下,编译器不会为std::atomic<UDT> 类型生 成无锁代码,所以它将对所有操作使用一个内部锁。如果用户提供的拷贝赋值或比较操作被 允许,那么这就需要传递保护数据的引用作为一个参数,这就有悖于指导意见了。当原子操作需要时,运行库也可自由的使用单锁,并且运行库允许用户提供函数持有锁,这样就有可 能产生死锁(或因为做一个比较操作,而组设了其他的线程)。最终,因为这些限制可以让编译 器将用户定义的类型看作为一组原始字节,所以编译器可以对 std::atomic<UDT> 直接使用原 子指令(因此实例化一个特殊无锁结构)。

注意,虽然使用std::atomic<float>或std::atomic<double>(内置浮点类型满足使用 memcpy和memcmp的标准),但是它们在compare_exchange_strong函数中的表现可能会 令人惊讶。当存储的值与当前值相等时,这个操作也可能失败,可能因为旧值是一个不同的 表达式。这就不是对浮点数的原子计算操作了。在使用compare_exchange_strong函数的过 程中,你可能会遇到相同的结果,如果你使用 std::atomic<> 特化一个用户自定义类型,且这个类型定义了比较操作,而这个比较操作与memcmp又有不同——操作可能会失败,因为两 个相等的值用有不同的表达式。

如果你的UDT类型的大小如同(或小于)一个int或void* 类型时,大多数平台将会对std::atomic<UDT> 使用原子指令。有些平台可能会对用户自定义类型(两倍于int或 void* 的 大小)特化的 std::atmic<> 使用原子指令。这些平台通常支持所谓的“双字节比较和交 换”(double-word-compare-and-swapDWCAS)指令,这个指令与compare_exchange_xxx 相关联着。这种指令的支持,对于写无锁代码是有很大的帮助,具体的内容会在第7章讨论。

以上的限制也意味着有些事情你不能做,比如,创建一个std::atomic<std::vector<int>> 类 型。这里不能使用包含有计数器,标志指针和简单数组的类型,作为特化类型。虽然这不会导致任何问题,但是,越是复杂的数据结构,就有越多的操作要去做,而非只有赋值和比 较。如果这种情况发生了,你最好使用 std::mutex 保证数据能被必要的操作所保护,就像第 3章描述的。

当使用用户定义类型T进行实例化时,std::atomic<T>的可用接口就只有: load(), store(),  exchange(), compare_exchange_weak(), compare_exchange_strong()和赋值操作,以及向类型T转换的操作。表5.3列举了每一个原子类型所能使用的操作。

表5.3 每一个原子类型所能使用的操作

 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值