将相同的值写入相同的内存位置是否会导致数据争用?

问题描述 投票:0回答:4

考虑以下代码,该代码从多个线程将相同的值写入相同的内存位置:

void f(int* buf, int n, int* p) {
    for(int i = 0; i < n; i++)
        buf[i] = i;
    *p = buf[n/2];
}

void g(int* buf, int n) {
    int x1, x2;
    thread t1(f, buf, n, &x1);
    thread t2(f, buf, n, &x2);
    t1.join();
    t2.join();
    assert(x1 == x2);
}

虽然这很有趣,但我不太关心该标准提供了什么保证,因为我猜它没有提供任何保证。我真正关心的是上述代码在现实世界的多处理器硬件上的行为。

assert
是否总是会通过,或者是否有可能出现竞争条件、缓存同步问题等?

c++ multithreading memory synchronization race-condition
4个回答
9
投票

存在竞争,但在您的示例中,两个线程都会将相同的值写入相同的地址。由于您没有进行任何读取-修改-写入,而只是写入预定的数字,因此在大多数情况下这都是安全的。在大多数系统上,写入 int 将是一条原子指令。例外情况是,如果您在使用指令序列来存储 int 的 8 位微处理器上运行此代码。在这种情况下,它也可能仍然有效,但取决于执行多字节存储的库代码的实现。


6
投票

当一个线程进行的写入的效果可由另一个线程观察到时,与多线程相关的内存模型。在您发布的代码中,两个线程将相同的值写入相同的内存位置,因此哪个线程的写入

buf[n/2]
读取并不重要,任一线程都可以。

现代处理器采用缓存一致性协议,例如MESI,因此当线程同时写入缓冲区时,CPU 之间将发送大量消息来同步保存缓冲区的缓存线,从而使其运行速度比非并发场景下(假共享效果)。

这里写入是否是原子的并不重要,因为两个线程将相同的值写入相同的内存位置。有一场竞赛,但哪个线程获胜并不重要,因为即使部分写入,观察到的值也将是相同的。


3
投票

这里的关键点确实是,正如 @Maxim 所说,缓存一致性。在缓存一致性架构中,这确实是不可能的。

但是,在没有缓存一致性的机器上,它可能会出现问题。我不知道具体的架构,虽然它们由于自然选择而几乎灭绝,但据我所知还有一些剩余的。 (如果你知道例子,请评论。)

这是一个表,表示两个线程的执行,并用 1 填充内存中的零区域。为简洁起见,此示例按比例缩小了 32 倍,即此处的每个数字代表所讨论的 4 字节 int。缓存行大小为 4 个整数 == 4 个数字。标记为“刷新”的行是将片上高速缓存刷新到主存储器的点。实际上,它是不确定的,因为它可能随时发生,例如由于抢占式任务切换。

Core 1 cache Memory Core 2 cache ------------------------------------------------------------------------------ 0000 0000 (load cache) 0000 1000 (set 1st bit) 0000 1100 (set 2nd bit) 0000 0000 (load cache) **** (flush) 1100 1100 1000 (set 1st bit) 1000 **** (flush) 1000 1000 (load cache) 1000 1100 (set 2nd bit) 1000 (load cache) 1000 1110 (set 3rd bit) 1010 (set 3rd bit) 1000 1111 (set 4th bit) 1011 (set 4th bit) 1111 **** (flush) **** (flush) 1011
所以我们最终得到了错误的结果。

我再次强调,

这个反例仅在缓存不连贯的机器上有效


0
投票
CPP 参考资料说:

当表达式的计算

写入到内存位置并且 另一个评估读取修改相同的内存位置, 据说表达式是冲突的。一个程序有两个冲突 评估存在数据竞争,除非:

  • 两个评估都在同一线程或同一信号中执行 处理程序,或

  • 两个相互冲突的评估都是原子操作(参见 std::atomic),或

  • 其中一个相互矛盾的评估发生在 另一个(参见 std::memory_order)。

如果发生数据竞争,则程序的行为是未定义的。

--

CPP 参考文献说

“修改”,而不是“写入”。将相同的值写入内存位置不算作修改。因此,不存在冲突;因此,没有数据竞争。

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