标签: stdatomic

放宽原子规则的(轻微)区别是什么?

在看到 Herb Sutters关于“原子武器”的精彩演讲后,我对放松原子的例子感到有些困惑。

我认为C++ 内存模型(SC-DRF = Sequentially Consistent for Data Race Free)中的原子在加载/读取时执行“获取”。

我知道对于负载 [和存储] 是默认值std::memory_order_seq_cst,因此两者是相同的:

myatomic.load();                          // (1)
myatomic.load(std::memory_order_seq_cst); // (2)
Run Code Online (Sandbox Code Playgroud)

到目前为止一切都很好,没有涉及放松的原子(在听完演讲后,我永远不会使用放松的原子。永远。承诺。但当有人问我时,我可能不得不解释......)。

但是为什么我使用时它是“宽松”的语义

myatomic.load(std::memory_order_acquire);   // (3)
Run Code Online (Sandbox Code Playgroud)

既然负载获取不是释放,为什么这与(1)和不同(2)究竟在这里放松?

我唯一能想到的就是我误解了load意味着acquire。如果这是真的,并且默认值seq_cst意味着两者,那不就意味着一个完整的围栏 - 没有任何东西可以传递该指令,也不能传递?我一定误解了那部分。

[并且对称地用于存储释放]。

c++ memory-model memory-barriers stdatomic relaxed-atomics

2
推荐指数
1
解决办法
1474
查看次数

原子存储抛出错误

我最近升级到了 C++11 兼容编译器,并且尝试将一些代码从 boost 更新到 c++11 标准。我在使用atomic_store转换一些代码时遇到了问题。这是一些简单的测试代码,似乎会引发编译器错误。

int main()
{
    std::shared_ptr<int> m = std::make_shared<int>();
    *m = 1;

    std::shared_ptr<int> a =  std::make_shared<int>();
    *a = 2;

    std::atomic_store(&m,std::move(a));

    std::cout << *m << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

std::atomic_store(&m,std::move(a));行为我抛出编译器错误:

'std::shared_ptr<int>' is not derived from 'volatile std::atomic<_ITp>'
     std::atomic_store(&m,std::move(a));
                                      ^
Run Code Online (Sandbox Code Playgroud)

从 boost 迁移到 C++11 时,atomic_store 的方式是否发生了变化?我现在需要创建共享指针的原子对象吗?

c++ c++11 stdatomic

2
推荐指数
1
解决办法
1383
查看次数

原子释放可以“覆盖”吗?

假设我让atomic<int> i;线程 A 使用 memory_order_release 执行原子存储/交换。接下来,线程 B 使用 memory_order_release 执行原子存储。线程 C 执行原子 fetch_add(0, memory_order_acquire);

线程 C 是否从线程A 和 B仅从线程 B获取依赖项?

c++ atomic atomicity memory-barriers stdatomic

2
推荐指数
1
解决办法
128
查看次数

atomic_load() 和赋值有什么区别?

我正在开发一个处理大量原子操作的项目。到目前为止,我还不知道\xe2\x80\x99t atomic_load(),并且仅依靠赋值运算符来获取原子类型的值,并且除了这么多测试之外,我还没有\xe2\x80\x99t看到错误。这些原子类型会被多个进程和线程以及 更改atomic_compare_exchange_strong_explicit(),因此它们每次都需要一个旧值,而 \xe2\x80\x99s 我总是这样做,oldValue = <Atomic_ type_variable>并且它总是工作正常。\n这只是偶然吗?我应该更喜欢使用atomic_load()吗?

\n

rvalue lvalue-to-rvalue c11 stdatomic

2
推荐指数
1
解决办法
2648
查看次数

非原子&lt;&gt;指针上的原子操作可以比原子&lt;&gt;安全且更快吗?

我有十几个线程读取指针,并且一个线程可能每小时左右更改该指针一次。

读者对时间超级、超级、超级敏感。我听说这个atomic<char**>或其他什么是进入主内存的速度,我想避免这种情况。

在现代(比如2012年及以后)服务器和高端桌面Intel中,8字节对齐的正则指针能否保证正常读写时不会撕裂?我的测试运行了一个小时,没有看到撕裂。

否则,如果我以原子方式进行写入并正常读取,会更好(或更糟)吗?例如通过将两者结合起来?

请注意,还有其他有关混合原子和非原子操作的问题,这些问题没有指定 CPU,并且讨论会转向语言法律主义。这个问题与规范无关,而是关于到底会发生什么,包括我们是否知道在未定义规范的情况下会发生什么。

c++ performance x86-64 c++11 stdatomic

2
推荐指数
1
解决办法
1075
查看次数

C11 独立内存屏障 LoadLoad StoreStore LoadStore StoreLoad

我想在原子和非原子操作之间使用独立的内存屏障(我认为无论如何它都不重要)。我想我了解存储屏障和加载屏障的含义以及 4 种可能的内存重新排序;LoadLoad, StoreStore, LoadStore, StoreLoad.

但是,我总是发现获取/释放概念令人困惑。因为在阅读文档时,acquire 不仅说到loads,还说到stores,而release 不仅说到stores,还说到loads。另一方面,普通负载障碍仅为您提供负载保证,而普通商店障碍仅为您提供商店保证。

我的问题如下。在 C11/C++11 中,将独立atomic_thread_fence(memory_order_acquire)视为负载屏障(防止LoadLoad重新排序)和atomic_thread_fence(memory_order_release)存储屏障(防止StoreStore重新排序)是否安全?

如果以上是正确的,我可以用什么来防止LoadStoreStoreLoad重新排序?

当然,我对可移植性感兴趣,我不在乎上述在特定平台上产生什么。

c c++ memory-model memory-barriers stdatomic

2
推荐指数
1
解决办法
368
查看次数

当外部基础类型未按要求对齐时的atomic_ref

我在p0019r8上读到以下内容:

atomic_ref(T& obj);
Run Code Online (Sandbox Code Playgroud)

要求:引用的对象应与 对齐required_alignment

当未对齐时, cppreference将其解释为 UB:

如果 obj 未与 required_alignment 对齐,则行为未定义。


那么您期望实现如何处理它呢?

并且实现可以检查编译时 alignof,但实际上类型可能比对齐更对齐alignof。实现可以解释指针位并检查运行时对齐,但这是额外的运行时检查。

最终我看到以下选项:

  • 什么都不做 - 以令人不快的方式实现运行时未定义的行为,仅支持正确的使用
  • 检查编译时对齐 ( alignof) 并在错误时发出警告
  • 检查编译时对齐 ( alignof) ,如果错误不正确,则编译时失败,因为实际对齐可能大于静态类型可见的对齐
  • 检查编译时对齐 ( alignof),如果错误不正确,则在运行时失败,因为实际对齐可能大于静态类型可见的对齐
  • 检查编译时对齐 ( alignof) 并在错误时回退到基于锁
  • 检查运行时对齐(指针位),如果错误则在运行时失败
  • 检查运行时对齐(指针位),如果错误则回退到基于锁

c++ memory-alignment undefined-behavior stdatomic c++20

2
推荐指数
1
解决办法
332
查看次数

为什么使用原子 CAS 的程序不能保持线程安全?


int main(){

    atomic<bool> atomic_lock(false);
    std::atomic_flag lock_flag = ATOMIC_FLAG_INIT;
    int count = 0;


    auto f = [&](){
        bool flag = false;
        
        for( int i = 0; i< 10000000; ++i){
          while(!atomic_lock.compare_exchange_strong(flag, true)){}
          //while(lock_flag.test_and_set(std::memory_order_seq_cst));

          ++count;
          //lock_flag.clear(std::memory_order_seq_cst);
          atomic_lock.store(false, std::memory_order_seq_cst);
        }
    };

    thread t1(f);
    thread t2(f);
    t1.join();
    t2.join();

    cout<<count<<endl;

    return 0;
}

Run Code Online (Sandbox Code Playgroud)

这是我的程序,我想用 CAS 替换互斥锁,但不是 20000000 的输出表明它不是线程安全程序,哪里错了?但是,我用 atomic_flag 替换 atomic 显示如上,输出是正确的

c++ thread-safety c++11 stdatomic

2
推荐指数
1
解决办法
70
查看次数

可以通过其他获取操作获取负载重新排序吗?cppreference 说只有非原子的和宽松的通过 acquire 排序

根据C++ Referencemutex.lock()是一个memory_order_acquire操作,并且mutex.unlock()是一个memory_order_release操作。

然而,memory_order_acquirememory_order_release只对非原子和宽松原子操作有效。

memory_order:释放-获取cppreference 上的排序

如果线程 A 中的原子存储被标记memory_order_release,并且线程 B 中来自同一变量的原子加载被标记memory_order_acquire,则从线程 A 的角度来看,所有内存写入(非原子和宽松原子)发生在原子存储之前,在线程 B 中变得可见的副作用

C++中的互斥体能否保证原子操作的可见性?示例如下。代码可以A在 , 之前重新排序mu.lock(),并且线程bx为 吗false


#include <thread>
#include <atomic>
#include <cassert>
#include <iostream>
#include <unistd.h>

std::atomic<bool> x = {false};
std::mutex mu;

void write_x(){
  mu.lock();
  std::cout << "write_x" << std::endl;
  x.store(true, std::memory_order_release);
  mu.unlock();
}

void read_x() {
  mu.lock();
  std::cout …
Run Code Online (Sandbox Code Playgroud)

c++ mutex atomic memory-model stdatomic

2
推荐指数
1
解决办法
238
查看次数

C++调用过程中对象被销毁怎么办

这是我的测试代码

class bar
{
public:
    explicit bar(int x) : num(x) {}
    int get_num()
    {
        return num;
    }

private:
    int num;
};

shared_ptr<bar> ptr_store;

void get_func()
{
    while (1)
        printf("get_num:%d\n", ptr_store->get_num());
};

void set_func()
{
    while (1)
        //ptr_store = make_shared<bar>(1);
        atomic_exchange(&ptr_store, make_shared<bar>(1));

}

int main()
{
    ptr_store = make_shared<bar>(-1);
    std::thread t1(get_func);
    std::thread t2(set_func);
    t1.join();
    t2.join();
}
Run Code Online (Sandbox Code Playgroud)

我想知道为什么这个程序不会进行核心转储?

如果set_func在使用时t2破坏原点,是否会导致某些故障?是否由 保证?或者这只是一个巧合。ptr_storet1ptr_store->get_num()shared_ptr

Test environment:
OS: Ubuntu 20.04 LTS
Clang: clang version 3.9.1
G++: gcc version 7.5.0 …
Run Code Online (Sandbox Code Playgroud)

c++ multithreading shared-ptr c++11 stdatomic

2
推荐指数
1
解决办法
117
查看次数