gpt4 book ai didi

c++ - 可以将 std::atomic 与 POD 结构一起使用,除了它有一个构造函数吗?

转载 作者:太空狗 更新时间:2023-10-29 20:01:52 28 4
gpt4 key购买 nike

我正在使用一些原子变量,都是无符号整数,我想将它们收集到一个结构中——实际上是一个 POD。但是,我还想要一个构造函数,因为我的编译器不完全是 c++11(所以我必须定义自己的构造函数以使用初始值创建它)。

原来我有:

// Names are not the real names - this is just for example
std::atomic<int> counter1;
std::atomic<int> counter2;
std::atomic<int> counter3;

然后我很乐意根据需要增加/减少它们。但后来我决定我想要更多的计数器,因此将它们放入一个结构中:

struct my_counters {
int counter1;
int counter2;
int counter3;
// Constructor so that I can init the values I want.
my_counters(c1, c2, c3) : counter1(c1), counter2(c2), counter3(c3){;}
};

但由于我添加了自定义构造函数,从技术上讲,这不再是 POD。我正在阅读有关此的其他问题,他们说要使用 std::atomic 我需要一个 POD,但我阅读的其他问题表明该结构需要可复制或类似的东西......无论如何,我感到困惑,我想要了解我是否可以安全地将我的结构 my_counters 用作原子类型:

std::atomic<my_counters> counters;

然后在各种线程中:

// Are these operations now still atomic (and therefore safe to use across threads):
counters.counter1++;
counters.counter2--;
counters.counter3 += 4;

最佳答案

其他人已经说过,但为了清楚起见,我认为你需要这个:

struct my_counters {
std::atomic<int> counter1;
std::atomic<int> counter2;
std::atomic<int> counter3;
// Constructor so that I can init the values I want.
my_counters(c1, c2, c3) : counter1(c1), counter2(c2), counter3(c3){;}
};

然后简单地:

my_counters counters;

换句话说,原子的是计数器,而不是结构。该结构只是用于将它们组合在一起并初始化它们。

Peter 编辑

如果您同时使用来自不同线程的这些计数器,您可能希望通过将每个计数器放在单独的缓存行中来避免线程之间的错误共享争用。 (通常为 64 字节)。您可以使用 C++11 alignas在成员上让编译器填充结构布局,或在每个 atomic 之间手动插入一些虚拟 char padding[60] 成员。

由我编辑

关于一般理解缓存的好链接 here .值得阅读。英特尔高速缓存行现在似乎是 64 字节,只是通过快速谷歌搜索,但不要引用我的话。

我的另一个编辑

下面的评论中已经说了很多关于使用 std::atomic 来处理(任意)类或结构的来龙去脉,例如

struct MyStruct
{

int a;
int b;
};

std::atomic<MyStruct> foo = { };

但我的问题是:这什么时候有用?具体来说,正如 ivaigult 指出的那样,您不能使用 std::atomic 来改变 MyStruct< 的个别成员 以线程安全的方式。你只能用它来加载、存储或交换整个东西,想要这样做并不常见。

我能想到的唯一合法用例是当您希望能够共享类似(例如)struct tm 的内容时。在线程之间以这样一种方式,线程永远不会看到它处于不一致的状态。然后,如果结构很小,您可能会在没有锁定特定平台的情况下逃脱,这很有用。如果你不能,请注意其中的含义(优先级反转是最严重的,对于实时代码)。

如果您确实想要在线程之间共享一个struct并能够以线程安全的方式更新单个成员,那么std::atomic 不会削减它(它也不是为了削减它而设计的)。然后,您必须求助于互斥锁,为了做到这一点,从 std::mutex 派生结构很方便,如下所示:

struct AnotherStruct : public std::mutex
{

int a;
int b;
};

现在我可以做(例如):

AnotherStruct bar = { };

bar.lock ().
bar.a++;
bar.b++;
bar.unlock ();

这允许您以线程安全的方式更新两个(可能以某种方式链接的)变量。

如果这一切对于那些经验丰富的事件家来说是显而易见的,我很抱歉,但我想澄清一下我自己的想法。它实际上与 OP 的问题无关。

关于c++ - 可以将 std::atomic 与 POD 结构一起使用,除了它有一个构造函数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50601726/

28 4 0
文章推荐: c++ - 具有 QList 函数的 QT 应用程序 "append"
文章推荐: c# - "Data source name not found and no default driver specified"错误
文章推荐: c# - C# 泛型是否支持类型签名约束?
文章推荐: C# List.RemoveAll() - 如何删除列表的一个子集?