原子操作如何不是同步操作?

问题描述 投票:1回答:3

标准说松弛的原子操作不是同步操作。但是其他线程看不到其操作结果的原子性。

例子here不会给出预期的结果,对吗?

我通过同步理解的是,所有线程都可以看到具有这种特征的操作的结果。

也许我不明白同步意味着什么。我逻辑中的漏洞在哪里?

c++ concurrency atomic
3个回答
2
投票

允许编译器和CPU重新排序内存访问。它是as-if rule,它假设是单线程进程。

在多线程程序中,内存顺序参数指定如何围绕原子操作排序内存访问。这是与原子性方面本身分离的原子操作的同步方面(“获取 - 释放语义”):

int x = 1;
std::atomic<int> y = 1;

    // Thread 1
    x++;
    y.fetch_add(1, std::memory_order_release);

    // Thread 2
    while ((y.load(std::memory_order_acquire) == 1)
    { /* wait */ }
    std::cout << x << std::endl;  // x is 2 now

虽然放松的内存顺序我们只获得原子性,但没有订购:

int x = 1;
std::atomic<int> y = 1;

    // Thread 1
    x++;
    y.fetch_add(1, std::memory_order_relaxed);

    // Thread 2
    while ((y.load(std::memory_order_relaxed) == 1)
    { /* wait */ }
    std::cout << x << std::endl;  // x can be 1 or 2, we don't know

事实上正如Herb Sutter在他出色的Atomic Weapons演讲中解释的那样,memory_order_relaxed使得多线程程序非常难以推理,并且只应在非常特殊的情况下使用,当原子操作与其之前或之后的任何其他操作之间没有依赖关系时。线程(很少这种情况)。


0
投票

是的,标准是正确的。松弛的原子不是同步操作,因为只保证了操作的原子性。

例如,

int k = 5;
void foo() {
    k = 10;
}

int baz() {
    return k;
}

在存在多个线程时,行为未定义,因为它暴露了竞争条件。在一些架构的实践中,可能会发生baz的调用者看到的也不是10,没有5,而是其他一些不确定的值。它通常被称为撕裂或脏读。

如果使用放松的原子载荷和存储,则baz将保证返回5或10,因为没有数据竞争。

值得注意的是,出于实际目的,英特尔芯片及其非常强大的内存模型在这种通用架构上使轻松的原子成为noop(意味着它没有额外的原子成本),因为加载和存储在硬件级别上是原子的。


0
投票

假设我们有

std::atomic<int> x = 0;

// thread 1
foo();
x.store(1, std::memory_order_relaxed);

// thread 2
assert(x.load(std::memory_order_relaxed) == 1);
bar();

首先,不保证线程2将观察值1(即断言可能触发)。但即使线程2确实观察到值1,而线程2正在执行bar(),它可能不会观察到线程1中foo()生成的副作用。如果foo()bar()访问相同的非原子变量,则可能发生数据争用。

现在假设我们将示例更改为:

std::atomic<int> x = 0;

// thread 1
foo();
x.store(1, std::memory_order_release);

// thread 2
assert(x.load(std::memory_order_acquire) == 1);
bar();

仍然无法保证线程2观察到值1;毕竟,可能会发生负载发生在商店之前。但是,在这种情况下,如果线程2观察到值1,则线程1中的存储与线程2中的加载同步。这意味着在线程1中存储之前排序的所有内容都发生在加载后排序的所有内容之前因此,bar()将看到foo()产生的所有副作用,如果它们都访问相同的非原子变量,则不会发生数据竞争。

因此,正如您所看到的,x上的操作的同步属性不会告诉您x会发生什么。相反,同步会对两个线程中的周围操作进行排序。 (因此,在链接示例中,结果始终为5,并且不依赖于内存排序; fetch-add操作的同步属性不会影响fetch-add操作本身的效果。)

© www.soinside.com 2019 - 2024. All rights reserved.