gpt4 book ai didi

c++ - 竞争条件和解锁写入

转载 作者:搜寻专家 更新时间:2023-10-31 00:01:28 24 4
gpt4 key购买 nike

我有一个关于竞争条件和同步写入的问题。

我有一个类,它的对象可以从不同的线程访问。我想只按需计算一些值并缓存结果。出于性能原因,我宁愿不使用锁(在任何人问之前 - 是的,它与我的情况相关)。

这构成了竞争条件。但是,对象是常量,不会更改。因此,如果不同的线程计算要缓存的值,在我的用例中,它们保证是相同的。在没有锁定的情况下写入这些值是否安全?或者,更广泛地说,在没有锁定的情况下从不同的线程将相同的内容写入内存是否安全?

写入的值是 bool 和 double 类型,所讨论的架构可能是 x86 和 ARM。

编辑:感谢大家的投入。我终于决定找到一种不涉及缓存的方法。这种方法看起来确实很像“hack”,并且使用标志变量存在问题。

最佳答案

正如您所说,这是一个竞争条件。在 C++11 下,它在技术上是一个数据竞争,并且是未定义的行为。值是否相同并不重要。

如果你的编译器支持它(例如最近的 gcc,或者我的 Just::Thread 库中的 gcc 或 MSVC)那么你可以使用 std::atomic<some_pod_struct>为您的数据提供一个原子包装器(假设它一个 POD 结构——如果不是,那么您有更大的问题)。如果它足够小,那么编译器将使它成为无锁的,并使用适当的原子操作。对于较大的结构,库将使用锁。

在没有原子操作或锁的情况下执行此操作的问题是可见性。虽然在 x86 或 ARM 上的处理器级别上将相同的数据(假设它确实是逐字节相同的)从多个线程/处理器写入同一内​​存没有问题,但我希望这是一个缓存如果它已经被写入,你会想要读取这些数据而不是重新计算它。因此,您需要某种标志来指示完成。除非您使用原子操作、锁或合适的内存屏障指令,否则“就绪”标志可能会在数据之前对另一个处理器可见。这真的会把事情搞砸,因为第二个处理器现在读取的是一组不完整的数据。

您可以使用非原子操作写入数据,然后为标志使用原子数据类型。在 C++11 下,这将生成合适的内存屏障和同步,以确保数据对看到标志集的任何线程都是可见的。两个线程写入数据仍然是未定义的行为,但在实践中可能没问题。

或者,将数据存储在由每个执行计算的线程分配的堆内存块中,并使用比较和交换操作来设置原子指针变量。如果比较和交换失败,则另一个线程首先到达那里,因此释放数据。

关于c++ - 竞争条件和解锁写入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9998281/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com