标签: stdatomic

如果必须检查溢出或有条件地执行操作,std::atomic 是否是多余的?

例如,您可以安全地递增和递减 std::atomic_int 。但是,如果您需要检查溢出或根据该值有条件地执行某些例程,那么无论如何都需要锁。由于您必须比较该值,并且在比较成功后线程可能会被交换,另一个线程会修改,...bug。

但如果你需要锁,那么你可以使用普通整数而不是原子。我对吗?

c++ atomic overflow c++11 stdatomic

4
推荐指数
1
解决办法
876
查看次数

为什么这个“std::atomic_thread_fence”起作用

首先我想谈一下我对此的一些理解,如有错误请指正。

  1. aMFENCE在x86中可以保证全屏障
  2. 顺序一致性可防止 STORE-STORE、STORE-LOAD、LOAD-STORE 和 LOAD-LOAD 重新排序

    这是根据维基百科的说法。

  3. std::memory_order_seq_cst不保证防止 STORE-LOAD 重新排序。

    这是根据Alex 的回答,“负载可能会通过早期存储重新排序到不同位置”(对于 x86),并且 mfence 不会总是被添加。

    a是否std::memory_order_seq_cst表示顺序一致性?根据第2/3点,我认为这似乎不正确。std::memory_order_seq_cst仅当以下情况时才表示顺序一致性

    1. 至少一个显式MFENCE添加到任一LOADSTORE
    2. LOAD(无栅栏)和 LOCK XCHG
    3. LOCK XADD ( 0 ) 和 STORE (无栅栏)

    否则仍有可能重新订购。

    根据@LWimsey的评论,我在这里犯了一个错误,如果 和LOAD都是STOREmemory_order_seq_cst则没有重新排序。Alex 可能指出使用非原子或非 SC 的情况。

  4. std::atomic_thread_fence(memory_order_seq_cst)总是产生一个完整的屏障

    这是根据Alex的回答。所以我总是可以替换asm volatile("mfence" ::: "memory")std::atomic_thread_fence(memory_order_seq_cst)

    这对我来说很奇怪,因为memory_order_seq_cst原子函数和栅栏函数之间的用法似乎有很大不同。

现在我在MSVC 2015的标准库的头文件中找到这段代码,它实现了std::atomic_thread_fence

inline void _Atomic_thread_fence(memory_order _Order)
    {   /* …
Run Code Online (Sandbox Code Playgroud)

c++ x86 memory-barriers stdatomic

4
推荐指数
1
解决办法
2212
查看次数

Red Hat: using <atomic> compiles fine but linker can't find __atomic_store_16; what library?

I'm using atomic<> for the first time, and just as using <thread> requires you to link a thread library, it seems like using <atomic> wants you to do... something. What?

> uname -a
Linux sdclxd00239 3.10.0-693.11.6.el7.x86_64 #1 SMP Thu Dec 28 14:23:39 EST 2017 x86_64 x86_64 x86_64 GNU/Linu

> g++ Foo.cxx -g -o MsgQueueNoLock -pthread
/tmp/ccnGOKUG.o: In function `std::atomic<Ptr_T>::store(Ptr_T, std::memory_order)':
/opt/rh/devtoolset-7/root/usr/include/c++/7/atomic:239: undefined reference to `__atomic_store_16'
/tmp/ccnGOKUG.o: In function `std::atomic<Ptr_T>::load(std::memory_order) const':
/opt/rh/devtoolset-7/root/usr/include/c++/7/atomic:250: undefined reference to `__atomic_load_16'
collect2: error: ld returned 1 …
Run Code Online (Sandbox Code Playgroud)

c++ gcc redhat linker-errors stdatomic

4
推荐指数
1
解决办法
3316
查看次数

为什么 stdatomic.h 包含 atomic_uint_least16_t 和 atomic_uint_fast16_t 但不包含 atomic_uint16_t?

stdatomic.h似乎包含 atomic_uint_least16_tand atomic_uint_fast16_t,它们是and类型的_Atomic版本,但它不包含. 为什么?stdint.h uint_least16_tuint_fast16_tatomic_uint16_t


有关N1548 草案的一些背景信息:

7.18.1.1 精确宽度整数类型

1 typedef 名称intN_t指定宽度为 N、无填充位和二进制补码表示的有符号整数类型。因此,int8_t表示具有恰好 8 位宽度的这种有符号整数类型。

2 typedef 名称uintN_t指定宽度为 N 且无填充位的无符号整数类型。因此,uint24_t表示具有恰好 24 位宽度的这种无符号整数类型。

3 这些类型是可选的。但是,如果实现提供宽度为 8、16、32 或 64 位、无填充位且(对于有符号类型)具有二进制补码表示的整数类型,则应定义相应的 typedef 名称。

7.18.1.2 最小宽度整数类型

1 typedef 名称int_leastN_t指定宽度至少为 N 的有符号整数类型,这样尺寸较小的有符号整数类型都不会至少具有指定的宽度。因此,int_least32_t表示宽度至少为 32 位的有符号整数类型。

2 typedef 名称uint_leastN_t指定宽度至少为 N 的无符号整数类型,因此没有较小尺寸的无符号整数类型至少具有指定的宽度。因此,uint_least16_t表示宽度至少为 16 …

c language-lawyer stdint c11 stdatomic

4
推荐指数
1
解决办法
137
查看次数

如果仅写入值,我是否需要原子?

假设我有多个线程访问相同的内存位置。而且,如果有的话,它们都写入相同的值,但没有人读取它。之后,所有线程(通过锁)收敛,然后我才读取值。我需要为此使用原子吗?这是针对 x86_64 系统的。该值是一个 int32。

c c++ assembly x86-64 stdatomic

4
推荐指数
1
解决办法
386
查看次数

加载/存储松弛原子变量和普通变量有什么区别?

正如我从测试用例中看到的:https : //godbolt.org/z/K477q1

生成的程序集加载/存储原子放松与普通变量相同:ldr 和 str

那么,松弛原子变量和普通变量之间有什么区别吗?

c++ atomic memory-barriers c++11 stdatomic

4
推荐指数
3
解决办法
822
查看次数

&lt;atomic&gt; 的 CMPXCHG16B 和 MSVC 实现不是默认的?

似乎要使用 CMPXCHG16B,必须定义 _STD_ATOMIC_ALWAYS_USE_CMPXCHG16B = 1 以便使用这些指令。

为什么这是默认设置?除非我阅读整个 atomic.h 标头,否则我永远不会发现这一点。

STL 中还有哪些其他全局定义?是否有一份清单可供审查,以便人们能够可靠地了解这些实施细节?

c++ x86-64 visual-c++ compare-and-swap stdatomic

4
推荐指数
1
解决办法
146
查看次数

没有真正理解 std::atomic::compare_exchange_weak 和compare_exchange_strong 的逻辑

我读过https://en.cppreference.com/w/cpp/atomic/atomic/compare_exchange

以原子方式将 *this 的对象表示形式 (C++20 之前) 值表示形式 (C++20 起) 与预期的表示形式进行比较,如果它们按位相等,则将前者替换为所需的(执行读取-修改-写入操作) )。否则,将 *this 中存储的实际值加载到预期中(执行加载操作)。

据我了解,代码如下

bool expected=true;
extern atomic<bool> b = false; 
void foo ()
{
//
    while(!b.compare_exchange_weak(expected, false));
//
}
Run Code Online (Sandbox Code Playgroud)

循环运行一次后(忽略虚假失败)它将失败,并将写入预期false,因此在第二次迭代时,compare_exchange_weak将返回成功,尽管b尚未更改为true。但这一切有什么意义呢?我虽然可以用它作为同步锁,等待其他线程更改b,但现在我想不出它的用法。

cppreference 中的示例还表明,两次调用compare_exchange_strong 后将会成功。

#include <atomic>
#include <iostream>
 
std::atomic<int>  ai;
 
int  tst_val= 4;
int  new_val= 5;
bool exchanged= false;
 
void valsout()
{
    std::cout << "ai= " << ai
          << "  tst_val= " << tst_val
          << "  new_val= " << new_val
          << "  exchanged= …
Run Code Online (Sandbox Code Playgroud)

c++ multithreading atomic compare-and-swap stdatomic

4
推荐指数
1
解决办法
1066
查看次数

为什么逻辑 AND/OR 的左操作数不依赖于父计算?

根据C++标准:

\n
\n

如果 A 的值用作 B 的操作数,则求值 A 具有对求值 B 的依赖性,除非:

\n

\xe2\x80\x94 B 是 std::kill_dependency (29.3) 的任何特化的调用,或者

\n

\xe2\x80\x94 A 是内置逻辑 AND(&&,参见 5.14)或逻辑 OR(||,参见 5.15)运算符的左操作数,或者

\n

\xe2\x80\x94 A 是条件(?:,参见 5.16)运算符的左操作数,或者

\n

\xe2\x80\x94 A 是内置逗号 (,) 运算符的左操作数 (5.18);(...)

\n
\n

我可以理解为什么关系之前排序的依赖项会在kill_dependency调用时停止,但是为什么逻辑AND、OR、逗号等运算符也会破坏依赖链?

\n

这是否意味着下面的代码有未定义的行为?

\n
//thread1\nint y = 2\natomicVal.store(true);\n\n//thread2 \nauto x = atomicVal.load(std::memory_order_consume);\ncout << x && y;\n
Run Code Online (Sandbox Code Playgroud)\n

c++ atomic lock-free carries-dependency stdatomic

4
推荐指数
1
解决办法
150
查看次数

是对基本类型的非原子变量的并发写入和读取而不使用它的未定义行为吗?

在无锁的queue.pop()中,我在与循环内的原子获取同步后读取了一个trivialy_copyable变量(整型)。\n最小化的伪代码:

\n
//somewhere else writePosition.store(...,release)\n\nbool pop(size_t & returnValue){\nwritePosition = writePosition.load(aquire)\noldReadPosition = readPosition.load(relaxed)\nsize_t value{};\ndo{\n  value = data[oldReadPosition]\n  newReadPosition = oldReadPosition+1\n}while(readPosition.compare_exchange(oldReadPosition, newReadPosition, relaxed)\n// here we are owner of the value\nreturnValue = value;\nreturn true;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

data[oldReadPosition]仅当该值之前从另一个线程读取时,才能更改内存。

\n

读写位置都是 ABA 安全的。\n通过简单的复制,value = data[oldReadPosition]内存data[oldReadPosition]不会被改变。

\n

但是写入线程queue.push(...)可以在读取时更改data[oldReadPosition],前提是另一个线程已经读取了 oldPosition 并更改了 readPosition。

\n

如果您使用该值,这将是一个竞争条件,但是当我们保持value不变时,它是否也是一个竞争条件,从而导致未定义的行为?标准不够具体或者我不\xc2\xb4不理解它。\nimo,这应该是可能的,因为它没有效果。\n我会很高兴得到一个合格的答案以获得更深入的见解

\n

多谢

\n

c++ concurrency lock-free race-condition stdatomic

4
推荐指数
1
解决办法
297
查看次数