使用c++ atomic时写"y=++x"安全吗?
Is it safe to write "y=++x" when using c++ atomic?
如果我有 2 个线程并且在 main 函数中,我会像这样初始化一个变量 x
std::atomic<int> x=0;
,
在线程 1 中,我这样做:
while(true){
x++;
}
在线程 2 中,我这样做:
y=++x;
我的问题是 that:is 变量 y 有没有可能得到错误的数字?
我的意思是例如:
如果在线程2中,此时x=2;那么因为"++x",x=3,所以我希望y=3;
但是我怕在"++x"和"y=x"之间,线程1会再次重写x,所以我可能有y=4什么的。
is there any possibility that variable y can get the wrong number?
完全取决于您认为的 "wrong" 数字。 y
几乎可以有任何值,这取决于 trhead1 中的循环重复了多少次。
y
将保证获得 x
在预增量操作后的值。
x
确实可以在赋值之前递增,因此 x
的值可能大于 y
的值。关于 y
的值,我们唯一可以预测的是它不会大于 x
.
如果一个线程写入原子 object 而另一个线程从中读取,则行为是 well-defined。所以答案是否定的,y
不能得到一个"wrong"值,这就是<atomic>
header.
的全部目的
Pre-increment 和 post-increment 原子操作也是原子操作。
来自man page:
T operator++() noexcept;
T operator++() volatile noexcept;
Atomically increments or decrements the current value. The operation is read-modify-write operation.
1) Performs atomic pre-increment. Equivalent to fetch_add(1)+1.
所以是的,它很安全。
But I am afraid that between "++x" and "y=x",thread 1 will rewrite x
again,so I may have y=4 or something.
线程 1 可能会再次重写 x
,但线程 2 不会再次读取 x
的值,因此如果发生这种情况,它不会对线程 2 产生任何影响。分配给 y
的值取自从 fetch_add()
.
返回的 private/temporary
是的,您会得到正确的值。该接口保证该值将递增并 return 自动编辑。它还指出结果是按值 return 编辑的(而大多数预增量将 return 对现在增加的对象的引用)以避免其他线程进行任何意外更改。
这里是the docs.
如果担心 y=++x
中 x
中的值首先等于 2,然后通过 ++x
增加到 3,然后在复制到 [= 之前再次由另一个线程增加13=],那么答案是否定的——这不可能发生。操作 ++x
的结果不是对原子值本身的引用 - 它是 post-increment 的简单 int
结果,并且该操作保证您将在增量返回后获得准确的值(无需额外阅读)。
如果我有 2 个线程并且在 main 函数中,我会像这样初始化一个变量 x
std::atomic<int> x=0;
,
在线程 1 中,我这样做:
while(true){
x++;
}
在线程 2 中,我这样做:
y=++x;
我的问题是 that:is 变量 y 有没有可能得到错误的数字?
我的意思是例如:
如果在线程2中,此时x=2;那么因为"++x",x=3,所以我希望y=3;
但是我怕在"++x"和"y=x"之间,线程1会再次重写x,所以我可能有y=4什么的。
is there any possibility that variable y can get the wrong number?
完全取决于您认为的 "wrong" 数字。 y
几乎可以有任何值,这取决于 trhead1 中的循环重复了多少次。
y
将保证获得 x
在预增量操作后的值。
x
确实可以在赋值之前递增,因此 x
的值可能大于 y
的值。关于 y
的值,我们唯一可以预测的是它不会大于 x
.
如果一个线程写入原子 object 而另一个线程从中读取,则行为是 well-defined。所以答案是否定的,y
不能得到一个"wrong"值,这就是<atomic>
header.
Pre-increment 和 post-increment 原子操作也是原子操作。
来自man page:
T operator++() noexcept;
T operator++() volatile noexcept;
Atomically increments or decrements the current value. The operation is read-modify-write operation.
1) Performs atomic pre-increment. Equivalent to fetch_add(1)+1.
所以是的,它很安全。
But I am afraid that between "++x" and "y=x",thread 1 will rewrite x again,so I may have y=4 or something.
线程 1 可能会再次重写 x
,但线程 2 不会再次读取 x
的值,因此如果发生这种情况,它不会对线程 2 产生任何影响。分配给 y
的值取自从 fetch_add()
.
是的,您会得到正确的值。该接口保证该值将递增并 return 自动编辑。它还指出结果是按值 return 编辑的(而大多数预增量将 return 对现在增加的对象的引用)以避免其他线程进行任何意外更改。
这里是the docs.
如果担心 y=++x
中 x
中的值首先等于 2,然后通过 ++x
增加到 3,然后在复制到 [= 之前再次由另一个线程增加13=],那么答案是否定的——这不可能发生。操作 ++x
的结果不是对原子值本身的引用 - 它是 post-increment 的简单 int
结果,并且该操作保证您将在增量返回后获得准确的值(无需额外阅读)。