相关疑难解决方法(0)

为什么在x86上对自然对齐的变量进行整数赋值?

我一直在读这篇关于原子操作的文章,它提到了32位整数赋值在x86上是原子的,只要该变量是自然对齐的.

为什么自然对齐确保原子性?

c c++ concurrency x86 atomic

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

GCC通过`memory_order_seq_cst`重新排序.这是允许的吗?

使用基本seqlock的简化版本 ,gcc load(memory_order_seq_cst)在编译代码时重新排序原子上的非原子加载-O3.在使用其他优化级别进行编译或使用clang进行编译时(甚至打开O3),不会观察到此重新排序.这种重新排序似乎违反了应该建立的同步关系,我很想知道为什么gcc重新排序这个特定的负载,如果这甚至是标准允许的话.

考虑以下load功能:

auto load()
{
    std::size_t copy;
    std::size_t seq0 = 0, seq1 = 0;
    do
    {
        seq0 = seq_.load();
        copy = value;
        seq1 = seq_.load();
    } while( seq0 & 1 || seq0 != seq1);

    std::cout << "Observed: " << seq0 << '\n';
    return copy;
}
Run Code Online (Sandbox Code Playgroud)

在seqlock程序之后,这个阅读器旋转,直到它能够加载两个实例seq_,它们被定义为a std::atomic<std::size_t>,是偶数(表示编写器当前没有写入)并且相等(表示编写器没有写入value在两个负载之间seq_).此外,因为这些负载被标记为memory_order_seq_cst(作为默认参数),我会想象指令copy = value;将在每次迭代时执行,因为它不能在初始加载时重新排序,也不能在后者下面重新排序.

但是,生成的组件会value在第一次加载之前发出负载,seq_甚至在循环之外执行.这可能导致不正确的同步或撕裂的读取value不会被seqlock算法解决.另外,我注意到这只发生在 sizeof(value) …

c++ multithreading gcc memory-barriers stdatomic

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

如何使用C ++ 11原子库实现seqlock锁

我想使用c ++ 11原子库编写一个seqlock。我已阅读有关stackoverflow上seqlock的一些问题?但是没人帮我 我使用的算法很常见,您可以在任何地方找到它,这是我的代码:

struct sequence_spinlock_t {

    void write_lock() {
        lock.lock();
        flags.fetch_add(1, memory_order_acquire); //A

    }

    void write_unlock() {
        flags.fetch_add(1, memory_order_release); //B
        lock.unlock();
    }

    void read_enter(uintptr_t *flag) {
        for (;;) {
            uintptr_t f = flags.load(memory_order_acquire); //C
            if ((f & 1) == 0) {
                *flag = f;
                break;
            }
            pause();
        }
    }

    bool_ read_leave(uintptr_t flag) {                                        

        uintptr_t f = flags.load(memory_order_relaxed); //D
        return f == flag;
    }

    spinlock_t lock;
    atomic_uintptr_t flags;
};

    //read thread
    uintptr_t flag;
    do {
        lock.read_enter(&flag);      (0)
        //read something             (1) …
Run Code Online (Sandbox Code Playgroud)

c++ atomic c++11

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

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

在无锁的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
查看次数

用 32 位原子实现 64 位原子计数器

我想从原子 uint32s 拼凑一个 uint64 原子计数器。计数器有一个写入器和多个读取器。编写器是一个信号处理程序,所以它不能阻塞。

我的想法是使用低位的代数作为读锁。读取器重试,直到整个读取过程中生成计数稳定,并且低位未设置。

以下代码在内存排序的设计和使用中是否正确?有没有更好的办法?

using namespace std;
class counter {
    atomic<uint32_t> lo_{};
    atomic<uint32_t> hi_{};
    atomic<uint32_t> gen_{};

    uint64_t read() const {
        auto acquire = memory_order_acquire;
        uint32_t lo, hi, gen1, gen2;
        do {
            gen1 = gen_.load(acquire);
            lo = lo_.load(acquire);
            hi = hi_.load(acquire);
            gen2 = gen_.load(acquire);
        } while (gen1 != gen2 || (gen1 & 1));
        return (uint64_t(hi) << 32) | lo;
    }

    void increment() {
        auto release = memory_order_release;
        gen_.fetch_add(1, release);
        uint32_t newlo = 1 + lo_.fetch_add(1, release);
        if (newlo …
Run Code Online (Sandbox Code Playgroud)

c++ lockless c++11 stdatomic seqlock

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