是否可以使用 std::atomic 使类原子的复杂成员函数?

Posted

技术标签:

【中文标题】是否可以使用 std::atomic 使类原子的复杂成员函数?【英文标题】:Is it possible with std::atomic, make a complex member function of a class atomic? 【发布时间】:2013-06-10 11:40:59 【问题描述】:

有可能做这样的事情吗?

...
class test
int i;
public:
      test(int k):i(k);
      void my()
         cout<<i;
      

atomic<test> kk(0);
kk.test();
...

如果这是不可能的,那么如何调用函数以使其成为原子的?

【问题讨论】:

你为什么不试试呢? 谢谢,我试过了,它不知道t work that way. In kk there is no member function test. So i dont 知道如何调用它。所以问。如何从kk调用测试??? 如果你想要原子函数,你需要使用互斥体。 atomic&lt;&gt; 只给你a few operations on integers of various sizes。它不会神奇地使具有多个整数运算符的函数成为原子函数。 std::atomic&lt;Ty&gt; 对任意类型 Ty 进行了明确定义,前提是它们可以用 memcpy 复制并与 memcmp 比较相等性。 @WanderingLogic - 只要存储对象的大小足够小,std::atomic&lt;Ty&gt; 就可以无锁。我为 Dinkumware 编写的实现在所有情况下(包括数字类型)都使用 size 来确定是否使用锁。无论如何,我是在回应“atomic&lt;&gt; 只为您提供对各种大小的整数的一些操作”的断言。太窄了。 【参考方案1】:

std::atomic 的工作方式是使用处理器提供的某些指令。这些指令仅适用于特定大小的整数(不同的处理器对你能做什么和不能做什么有不同的限制和规则,在某些架构中,处理器架构甚至可能需要使用互斥锁或类似的功能来实现标准::原子)。

另请注意,std::atomic 的目的是确保值在多个处理器内核或多个处理器之间自动更新,这通常不是您想要/可以对更大的数据结构执行的操作。

要在其他数据结构上实现原子操作,您必须使用互斥锁或类似结构来确保以“线程原子”方式(不同于“处理器原子”)完成处理。

【讨论】:

C++ 规范的 31.8 [atomics.types.generic] 没有说明大小限制。只是它是简单的复制和移动构造和可分配的。另请注意static constexpr bool is_always_lock_free = implementation-defined; 成员。【参考方案2】:

可以创建包含非数字对象的 std::atomic 对象。主要限制是包含的类型必须是可简单复制的;松散地说(因为它是这样实现的),这意味着用memcpy复制是可以的,与memcmp比较是有意义的。但是,它不允许您调用存储对象的成员函数。您必须复制存储的对象,进行更新,然后将结果复制回原子对象。

【讨论】:

在 OP 的示例中,失败的是调用 kk.test()atomic 与使 test() 函数正确执行而没有读取-修改-更新原子性问题完全无关。 @WanderingLogic - 我的最后两句话就是这么说的。

以上是关于是否可以使用 std::atomic 使类原子的复杂成员函数?的主要内容,如果未能解决你的问题,请参考以下文章

第31课 std::atomic原子变量

C++ 原子操作 std::atomic<int>

std::atomic_ref 如何为非原子类型实现?

原子读取然后用 std::atomic 写入

使用原子的线程安全单例

std::atomic 与另一个字符联合