相关疑难解决方法(0)

"原子对象"的定义

在C和C++的标准术语,短语" 原子对象 "是指" 物体原子类型, "不是吗?

没有标准会明确定义每个双字短语,因此没有错误的C和C++标准,因为省​​略了这个短语的明确定义.然而,当我读到C++ 17标准(这里的草案)时,教派.4.7.1(4),即"所有的修改以使特定原子对象中号发生在一些特定的总次序,被称为修饰顺序中号 " -和当标准反复采用类似的语言来分隔以往更精确逻辑并发-I我想确保我不会无意中误解.

我是否正确地假设短语"原子对象"的意思

  • 对象原子类型

我能想象的唯一合理的选择是这个短语的意思

  • 正确对齐的对象足够小,硬件可以原子地处理它.

请问是哪一个?

(注意:我在C和C++上都标记了这个问题,因为当涉及原子时,这两个标准使用几乎相同的语言.因此,就我所知,任何一种语言的专家都可以回答.如果由于某种原因,我是错了,那么请删除C标签并保留C++.)

参考:另见这个问题,我的问题是初步的.

c c++ atomic definition language-lawyer

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

出于排序的目的,原子读-修改-写是一种操作还是两种操作?

考虑一个原子读-修改-写操作,例如x.exchange(..., std::memory_order_acq_rel)。出于对其他对象的加载和存储进行排序的目的,这是否被视为:

  1. 具有获取-释放语义的单个操作?

  2. 或者,作为一个获取加载,然后是一个释放存储,附加保证其他加载和存储x将同时观察它们或两者都不观察?

如果它是 #2,那么尽管在加载之前或存储之后不能对同一线程中的其他操作进行重新排序,但仍然存在在两者之间重新排序的可能性。

作为一个具体的例子,考虑:

std::atomic<int> x, y;

void thread_A() {
    x.exchange(1, std::memory_order_acq_rel);
    y.store(1, std::memory_order_relaxed);
}

void thread_B() {
    // These two loads cannot be reordered
    int yy = y.load(std::memory_order_acquire);
    int xx = x.load(std::memory_order_acquire);
    std::cout << xx << ", " << yy << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

可以thread_B输出0, 1吗?

如果x.exchange()换成了x.store(1, std::memory_order_release);那么thread_B肯定能输出0, 1。是否应该exchange()排除额外的隐式负载?

cppreference听起来像 #1 是这种情况并且0, 1被禁止:

具有此内存顺序的读-修改-写操作既是获取操作又是释放操作。当前线程中的任何内存读取或写入都不能在此存储之前或之后重新排序。

但是我在标准中找不到任何明确的内容来支持这一点。实际上,该标准对原子读-修改-写操作几乎没有说明,除了 N4860 …

c++ atomic memory-barriers stdatomic

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

ARM64:LDXR/STXR与LDAXR/STLXR

在iOS上,有两个类似的功能,OSAtomicAdd32OSAtomicAdd32Barrier.我想知道你什么时候需要Barrier变种.

拆卸后,它们是:

_OSAtomicAdd32:
ldxr    w8, [x1]
add     w8, w8, w0
stxr    w9, w8, [x1]
cbnz    w9, _OSAtomicAdd32
mov     x0, x8
ret     lr

_OSAtomicAdd32Barrier:
ldaxr   w8, [x1]
add     w8, w8, w0
stlxr   w9, w8, [x1]
cbnz    w9, _OSAtomicAdd32Barrier
mov     x0, x8
ret     lr
Run Code Online (Sandbox Code Playgroud)

在哪种情况下,您需要后者的Load-Acquire/Store-Release语义?可以LDXR/ STXR指令重新排序吗?如果可以,原子更新是否有可能在没有障碍的情况下"丢失"?从我所读到的,似乎不会发生这种情况,如果是真的,那你为什么需要这个Barrier变体呢?也许只有你碰巧还需要一个DMB其他目的?

谢谢!

arm atomic arm64

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

isync是否可以防止CPU PowerPC上的存储装入重新排序?

众所周知,PowerPC具有较弱的内存模型,它允许进行任何推测性的重新排序:存储-存储,加载-存储,存储-加载,加载-加载。

至少有3个栅栏:

例如,是否可以在此代码中重新排序“存储stwcx.和加载” lwz?:https : //godbolt.org/g/84t5jM

    lwarx 9,0,10
    addi 9,9,2
    stwcx. 9,0,10
    bne- 0,.L2
    isync
    lwz 9,8(1)
Run Code Online (Sandbox Code Playgroud)

如已知的,isync防止重新排序lwarxbne< - > any following instructions

但是是否可以isync防止重新排序stwcx.bne<-> any following instructions

即可以先stwcx.于以下Load-开始存储lwz,而比Load-之后执行完成lwz

即可以stwcx.将存储库预执行的存储早于随后的加载lwz开始存储到存储缓冲区,但是对所有CPU内核可见的实际存储到高速缓存的发生要晚于加载lwz完成?

我们从以下文档,文章和书籍中看到:

  • isync 不是内存围栏,而仅仅是指令围栏。

  • isync 对于访问存储器的其他处理器和机制,并不强制完成所有外部访问。

  • isync 不等待所有其他处理器检测到存储访问

  • isync …

concurrency assembly multithreading powerpc

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

是否会在其他线程中始终以相同顺序看到对不同线程中不同位置的两次原子写操作?

与我之前的问题类似,请考虑以下代码

-- Initially --
std::atomic<int> x{0};
std::atomic<int> y{0};

-- Thread 1 --
x.store(1, std::memory_order_release);

-- Thread 2 --
y.store(2, std::memory_order_release);

-- Thread 3 --
int r1 = x.load(std::memory_order_acquire);   // x first
int r2 = y.load(std::memory_order_acquire);

-- Thread 4 --
int r3 = y.load(std::memory_order_acquire);   // y first
int r4 = x.load(std::memory_order_acquire);
Run Code Online (Sandbox Code Playgroud)

怪异的结果 r1==1, r2==0,并r3==2, r4==0有可能在C ++ 11内存模型下,这种情况下?如果我要全部替换std::memory_order_acq_rel成该std::memory_order_relaxed怎么办?

在x86上,这样的结果似乎是被禁止的,请参见此SO问题,但我一般是在询问C ++ 11内存模型。

奖励问题:

我们都同意,与std::memory_order_seq_cst怪异的结果不会在C ++ 11被允许。现在,赫伯·萨特(Herb Sutter)在他著名的- …

c++ concurrency memory-model c++11 stdatomic

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