标签: stdatomic

了解compare_exchange_weak

下面的代码是来自https://www.cplusplus.com/reference/atomic/atomic/compare_exchange_weak/的compare_exchange_weak的示例

我不明白 Compare_exchange_weak while 循环内可以接受哪些类型的操作。

在示例中,只要compare_exchange 返回 false,他们就会将 newNode->next 值设置为 oldHead 指针。我不明白这怎么总是有效的。

如果另一个线程处于同一个循环中,并且它在我们设置 oldHead 指针的时间和在我们的线程上compare_exchange 成功的时间之间成功更改了 oldHead 指针,会发生什么情况?那么我们的 newNode 中就会有错误的头指针。我不明白为什么这是不可能的。

例如,如果我在设置 ->next 值后放置 sleep(5),或者在循环中进行一些长计算,这会起作用吗?

标记为“在这里可以安全做什么”的循环是我不明白的部分。

// atomic::compare_exchange_weak example:
#include <iostream>       // std::cout
#include <atomic>         // std::atomic
#include <thread>         // std::thread
#include <vector>         // std::vector

// a simple global linked list:
struct Node { int value; Node* next; };
std::atomic<Node*> list_head (nullptr);

void append (int val) {     // append an element to the list
  Node* oldHead = list_head;
  Node* newNode …
Run Code Online (Sandbox Code Playgroud)

c++ multithreading stdatomic

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

使用 memory_order_seq_cst 和 memory_order_release 可能的排序

参考下面的代码

auto x = std::atomic<std::uint64_t>{0};
auto y = std::atomic<std::uint64_t>{0};

// thread 1
x.store(1, std::memory_order_release);
auto one = y.load(std::memory_order_seq_cst);

// thread 2
y.fetch_add(1, std::memory_order_seq_cst);
auto two = x.load(std::memory_order_seq_cst);
Run Code Online (Sandbox Code Playgroud)

这里有可能onetwo都为 0 吗?


(我似乎遇到了一个错误,在上面的代码运行后,如果onetwo都可以保持 0 的值,则可以解释该错误。并且排序规则太复杂,我无法弄清楚上面可以进行哪些排序。)

c++ multithreading memory-barriers stdatomic c++20

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

多个读取器可以通过获取/释放顺序与同一写入器同步吗?

读完“行动中的并发”后,我找不到一个问题的答案 - 当我们在一个原子变量上有一个存储(释放)和许多加载(获取)时,读取副作用的标准是否有保证?假设我们有:

int i{};
atomic<bool> b{};

void writer(){
 i=42;
 b.store(true,memory_order_release);
}

void reader(){
 while(!b.load(memory_order_acquire))
    this_thread::yield();
 assert(i==42);
}
//---------------------
thread t1{writer},t2{reader},t3{reader};
Run Code Online (Sandbox Code Playgroud)

如果我们只有一个读取器,一切都可以,但是我们是否可以在 t2 或 t3 线程中断言失败?

c++ atomic memory-model memory-barriers stdatomic

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

将全局引用计数资源与原子同步——这里放松合适吗?

我有一个全局引用计数对象obj,我想通过使用原子操作来防止数据争用:

T* obj;                  // initially nullptr
std::atomic<int> count;  // initially zero
Run Code Online (Sandbox Code Playgroud)

std::memory_order_release我的理解是,我需要在写入后使用obj,以便其他线程知道它被创建:

void increment()
{
    if (count.load(std::memory_order_relaxed) == 0)
        obj = std::make_unique<T>();

    count.fetch_add(1, std::memory_order_release);
}
Run Code Online (Sandbox Code Playgroud)

同样,我需要std::memory_order_acquire在读取计数器时使用,以确保线程具有obj被更改的可见性:

void decrement()
{
    count.fetch_sub(1, std::memory_order_relaxed);

    if (count.load(std::memory_order_acquire) == 0)
        obj.reset();
}
Run Code Online (Sandbox Code Playgroud)

我不相信上面的代码是正确的,但我也不完全确定为什么。我觉得obj.reset()调用之后,应该有一个std::memory_order_release操作来通知其他线程。那是对的吗?

是否还有其他可能出错的事情,或者在这种情况下我对原子操作的理解完全错误?

c++ multithreading atomic c++11 stdatomic

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

Windows 上*单 CPU*(多核)上的 C++ 多线程是否存在“缓存一致性”问题?

(编辑:只是为了澄清:“缓存一致性”的问题是在不使用原子变量的情况下。)

是否有可能(单CPU情况:Windows可以在Intel / AMD / Arm CPU上运行),线程1运行在core-1上存储一个bool变量(例如)并且它保留在L1缓存中,而线程2在 core-n 上运行使用该变量,并且它会查找内存中该变量的另一个副本?

代码示例(为了演示该问题,我们假设这std::atomic_bool只是一个普通的bool):

#include <thread>
#include <atomic>
#include <chrono>

std::atomic_bool g_exit{ false }, g_exited{ false };

using namespace std::chrono_literals;

void fn()
{
    while (!g_exit.load(std::memory_order_acquire))
    {
        // do something (lets say it takes 1-4s, repeatedly)
        std::this_thread::sleep_for(1s);
    }

    g_exited.store(true, std::memory_order_release);
}

int main()
{
    std::thread wt(fn);
    wt.detach();

    // do something (lets say it took 2s)
    std::this_thread::sleep_for(2s);

    // Exit

    g_exit.store(true, std::memory_order_release);

    for (int i = 0; i < 5; …
Run Code Online (Sandbox Code Playgroud)

c++ multithreading cpu-architecture memory-barriers stdatomic

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

在传播缓存行时,内存控制器如何保证原子的内存顺序?

我目前正在深入研究std::atomicsC++ 内存模型。真正对我的思维模型有帮助的是 CPU 的存储和加载缓冲区的概念,它基本上是一个 fifo 队列,用于存储必须写入 L1 缓存或从 L1 缓存读取的数据,至少在英特尔架构中存在。据我了解,原子操作基本上是对 CPU 的指令,可防止包装类型在编译时或运行时撕裂并跨屏障重新排序写入或读取指令。为了说明我的思维模型中的差距,我很快就想出了这个例子:

演示

#include <atomic>
#include <iostream>
#include <thread>

int a;
int b;
int c;
std::atomic<int> x;
int e = 0;

auto thread1() {
    while(1) {
        a = 3;
        b = 5;
        c = 1;
        x.store(10, std::memory_order::release);
        e++;
        std::cout << "stored!" << std::endl;
    }
}

auto thread2() {
    while(1) {
        x.load(std::memory_order::acquire);
        std::cout << b << std::endl;
    }
}


int main() {
    [[maybe_unused]] auto t1 = …
Run Code Online (Sandbox Code Playgroud)

c++ atomic cpu-architecture memory-model stdatomic

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

为什么添加线程不能带来进一步的性能提升

我正在学习 C++ 多线程编程。我的测试程序很简单,功能就是统计一个原子变量从0到10000000(高一点也没关系)。我不明白为什么当我将线程数从8设置为16后,执行时间反而增加了一些而不是大幅下降。

std::atomic<int> atomicCounter{0};
void addcount(int threadId) {
    while(atomicCounter.load() < 10000000) {
        atomicCounter.fetch_add(1);
    }
}

void test() {
    const int maxNumThreads = 8;
    // Time::now() is to get the timestamp accurate to ns
    auto s_ts = Time::now();
    std::vector<std::thread> threads;
    for (int i = 0; i < maxNumThreads; i++) {
        threads.emplace_back([&]() {
            addcount(i);
        });
    }

    // join the threads
    for (auto& thread : threads) {
        thread.join();
    }
    threads.clear();
    auto e_ts = Time::now();
    LOG(INFO) << "Executing time : " << (e_ts …
Run Code Online (Sandbox Code Playgroud)

c++ concurrency multithreading stdatomic

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

std :: this_thread :: yield只是一个提示有问题吗?

同事和我讨论了一个假想的问题,当一个人想要实现自旋锁互斥std::atomic_flag,但也实现那个自旋锁而不是(真)但作为一个

while(true)
{
     cnt=0;
     while (cnt<yieldAfterTries)
     {
        //try to get lock
        cnt++;
     }
     std::this_thread::yield();

     // if got lock do work and then break;
}     
Run Code Online (Sandbox Code Playgroud)

基本上的想法是线程不能"很长一段时间"阻止其他人,即使它有一个实时优先级,因为它会在一段时间后产生...但是当我看到std :: yield的规范时我很惊讶它是一个建议,不是强制性的.

提供实现的提示,以重新安排线程的执行,允许其他线程运行.

http://en.cppreference.com/w/cpp/thread/yield

那会有问题吗?

c++ c++11 stdthread stdatomic

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

使用std :: atomic在C++ 11中编写一个线程安全的deque

我需要一个可以同时读/写的消息deque.只写就好了

std::atomic<std::deque<Message>> queue;
Run Code Online (Sandbox Code Playgroud)

这是一个包装类,它有一个std::deque<Message> queue_和一个std::mutex mutex_as数据成员,并锁定mutex_之前转发任何操作queue_

multithreading c++11 stdatomic

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

C++ 11 atomic:std :: memory_order代码可移植吗?

在像std :: atomic :: compare_exchange这样的函数中,有一些运行时参数,比如std :: memory_order_release,std :: memory_order_relaxed.(http://en.cppreference.com/w/cpp/atomic/atomic/compare_exchange)

我不确定这些内存顺序标志是否保证存在于各种cpu /架构中,如果某些cpus不支持标志,这个标志是否会导致崩溃或?似乎这些标志中的一些是为intel itanium等设计的,不确定std :: memory_order相关代码是否可移植.

你能提一些建议吗?

c++ multithreading portability memory-model stdatomic

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