根据这个https://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html,已发布的商店MOV在x86(包括x86-64)上实现为(进入内存).
根据他的http://en.cppreference.com/w/cpp/atomic/memory_order
memory_order_release:
具有此内存顺序的存储操作将执行释放操作:在此存储之后,不能对当前线程中的内存访问进行重新排序.这确保了当前线程中的所有写入在获取或相同原子变量的其他线程中可见,并且带有依赖关系到原子变量的写入在消耗相同原子的其他线程中变得可见.
我知道当使用memory_order_release时,之前完成的所有内存存储应该在此之前完成.
int a;
a = 10;
std::atomic<int> b;
b.store(50, std::memory_order_release); // i can be sure that 'a' is already 10, so processor can't reorder the stores to 'a' and 'b'
Run Code Online (Sandbox Code Playgroud)
问题:MOV对于这种行为,裸指令(没有明确的内存栅栏)是否足够?如何MOV告诉处理器完成以前的所有商店?
我std::thread在我的C++代码中使用一个不断轮询一些数据并将其添加到缓冲区.我使用a C++ lambda来启动这样的线程:
StartMyThread() {
thread_running = true;
the_thread = std::thread { [this] {
while(thread_running) {
GetData();
}
}};
}
Run Code Online (Sandbox Code Playgroud)
thread_running 是atomic<bool>在类头中声明的.这是我的GetData功能:
GetData() {
//Some heavy logic
}
Run Code Online (Sandbox Code Playgroud)
接下来我还有一个StopMyThread函数,我将其设置thread_running为false,以便它退出while中的while循环lambda block.
StopMyThread() {
thread_running = false;
the_thread.join();
}
Run Code Online (Sandbox Code Playgroud)
据我了解,我可以暂停和使用恢复该线程std::condition_variable的指出这里在我前面的问题.
但是,如果我只是使用std::atomic<bool> thread_running执行或不执行GetData()下面的逻辑,是否有缺点?
GetData() {
if (thread_running == false)
return;
//Some heavy logic
}
Run Code Online (Sandbox Code Playgroud)
与使用 …
我不知道如何创建以下内容:
std::pair<std::atomic<bool>, int>
Run Code Online (Sandbox Code Playgroud)
我总是总是得到
/usr/include/c++/5.5.0/bits/stl_pair.h:139:45:错误:使用已删除的功能'std :: atomic :: atomic(const std :: atomic&)'
:第一(__x),第二(std :: forward <_U2>(__ y)){}
我试过了
std::pair<std::atomic<bool>, int> pair = std::make_pair(true, 1); //doesn't work
std::pair<std::atomic<bool>, int> pair = std::make_pair({true}, 1); //doesn't work
std::pair<std::atomic<bool>, int> pair = std::make_pair(std::atomic<bool>(true), 1); //doesn't work
std::pair<std::atomic<bool>, int> pair = std::make_pair(std::move(std::atomic<bool>(true)), 1); //doesn't work
Run Code Online (Sandbox Code Playgroud)
我知道std :: atomic是不可复制的,那么您应该如何成对创建它?只是不可能吗?
我想在线程之间传达一些信息。原子听起来像是要使用的东西。我看看这个。并发现一个简单的结构像
struct MyType{
int val_a,val_b;
float vals_c[5];
};
Run Code Online (Sandbox Code Playgroud)
应该填写断言:
static_assert(
std::is_trivially_copyable<MyType>::value &&
std::is_copy_constructible<MyType>::value &&
std::is_move_constructible<MyType>::value &&
std::is_copy_assignable<MyType>::value &&
std::is_move_assignable<MyType>::value,
"MyType is not suitable for std::atomic");
Run Code Online (Sandbox Code Playgroud)
)
但是一个简单的程序作为
//... MyType and static_assert
int main(int argc,char *argv[]){
MyType a;
std::atomic<MyType> b;
b = a;
a = b;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
无法编译:
undefined reference to `__atomic_store'
undefined reference to `__atomic_load'
Run Code Online (Sandbox Code Playgroud)
我在 64 位 ubuntu 16.04 上使用 gcc 5.4 版。
使用的标志是: -pipe -g -std=gnu++11 -Wall -W -fPIC
这是完全错误的使用std::atomic吗?MyType 有什么要求?或者只是这个设置中缺少一些东西?
在 C++20 中,我们可以这样写:
double x;
double x_value = std::atomic_ref(x).load();
Run Code Online (Sandbox Code Playgroud)
有没有同样效果的功能?
我试过,std::atomic_load但似乎没有非原子对象的重载。
考虑下面的示例是打算等到另一个线程存储42在一个共享变量shared没有锁,无需等待线程终止,为什么会volatile T或std::atomic<T>会要求或建议,以保证并发正确性?
#include <atomic>
#include <cassert>
#include <cstdint>
#include <thread>
int main()
{
int64_t shared = 0;
std::thread thread([&shared]() {
shared = 42;
});
while (shared != 42) {
}
assert(shared == 42);
thread.join();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
使用 GCC 4.8.5 和默认选项,示例按预期工作。
我试图了解std::atomic_thread_fence(std::memory_order_seq_cst);栅栏的用途,以及它们与栅栏有何不同acq_rel。
到目前为止,我的理解是,唯一的区别是 seq-cst 栅栏影响 seq-cst 操作的全局顺序 ( [atomics.order]/4)。并且只有在实际执行 seq-cst 加载时才能观察到所述顺序。
所以我想,如果我没有 seq-cst 负载,那么我可以用 acq-rel 栅栏替换所有 seq-cst 栅栏,而不改变行为。那是对的吗?
如果这是正确的,为什么我会看到这样的代码“使用栅栏实现 Dekker 算法”,它使用 seq-cst 栅栏,同时保持所有原子读/写宽松?这是该博客文章中的代码:
std::atomic<bool> flag0(false),flag1(false);
std::atomic<int> turn(0);
void p0()
{
flag0.store(true,std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_seq_cst);
while (flag1.load(std::memory_order_relaxed))
{
if (turn.load(std::memory_order_relaxed) != 0)
{
flag0.store(false,std::memory_order_relaxed);
while (turn.load(std::memory_order_relaxed) != 0)
{
}
flag0.store(true,std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_seq_cst);
}
}
std::atomic_thread_fence(std::memory_order_acquire);
// critical section
turn.store(1,std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_release);
flag0.store(false,std::memory_order_relaxed);
}
void p1()
{
flag1.store(true,std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_seq_cst);
while (flag0.load(std::memory_order_relaxed))
{
if (turn.load(std::memory_order_relaxed) != 1)
{
flag1.store(false,std::memory_order_relaxed);
while …Run Code Online (Sandbox Code Playgroud) 当我看到这个 CPP Con 2017 网络研讨会时,Fedor Pikus 说:“它必须是直接初始化”
这是网络研讨会的链接。
这些初始化方法有什么区别?(随后,为什么它必须是“直接”初始化?为什么“间接”初始化是“不是”?)
// C++17 Compiler
#include <atomic>
class Example
{
std::atomic<bool> m_b1 = false; // 1-h
std::atomic<bool> m_b2{ false }; // 2-h
static void doSomethng()
{
std::atomic<bool> b1 = false; // 1-f
std::atomic<bool> b2{ false }; // 2-f
std::atomic<bool> b3(false); // 3-f
// Do something
}
};
Run Code Online (Sandbox Code Playgroud) 我正在阅读有关 C++ 中的内存顺序的内容。我可以很好地理解放松和获取-释放模型。但我正在努力解决顺序一致性问题。
如果我没记错的话,从cppreference来看,std::memory_order_seq_cst“操作”相当于:
std::memory_order_seq_cst但‘栅栏’又是怎样的情况呢?它相当于其中的哪一个?
如果和上面其中之一是等价的,那另外两个呢?
据我所知,如果是情况 1(获取栅栏),编译器可以自由地将任何写操作从栅栏上方移动到栅栏下方。类似地,如果是情况 2(释放栅栏),编译器可以自由地将任何读取操作从栅栏下方移动到栅栏上方。最后,如果是情况 3(acq-rel 栅栏),则不允许编译器跨栅栏移动任何指令。它是否正确?
我仍然很困惑。以上说法可能不正确。有不对的地方请指正。
atomic_flag_test_and_set 是的!atomic_flag_clear 是的!atomic_flag_test_and_clear 没有atomic_flag_set 没有如果您想在某些上下文中对事件设置标志,并在其他上下文中检查并清除事件,C/C++ 不允许您在每个上下文中执行单个原子调用。
您必须反转标志,因此清除事件上的标志,在检查事件时检查并设置标志。
没什么大不了的,但在这种情况下似乎是倒退的,特别是考虑到标志的默认状态为 false,这在相反的意义上意味着默认情况下会断言事件。
我想,也可以使用原子boolwith来代替。atomic_exchange
c++ ×10
stdatomic ×10
c++11 ×5
atomic ×3
concurrency ×2
std ×2
c++17 ×1
c++20 ×1
c11 ×1
memory-model ×1
std-pair ×1
stdthread ×1
test-and-set ×1
x86 ×1