gpt4 book ai didi

c++ - 两个不同的进程在同一地址上有 2 个 std::atomic 变量?

转载 作者:太空狗 更新时间:2023-10-29 20:34:04 25 4
gpt4 key购买 nike

我阅读了 C++ 标准 (n4713) 的 § 32.6.1 3:

Operations that are lock-free should also be address-free. That is, atomic operations on the same memory location via two different addresses will communicate atomically. The implementation should not depend on any per-process state. This restriction enables communication by memory that is mapped into a process more than once and by memory that is shared between two processes.

所以听起来好像可以在同一内存位置上执行无锁原子操作。我想知道如何做到这一点。

假设我在 Linux 上有一个命名的共享内存段(通过 shm_open() 和 mmap())。例如,如何对共享内存段的前 4 个字节执行无锁操作?

起初,我以为我可以 reinterpret_cast指向 std::atomic<int32_t>* 的指针.但后来我读了this .它首先指出 std::atomic 可能不具有相同大小的 T 或对齐方式:

When we designed the C++11 atomics, I was under the misimpression that it would be possible to semi-portably apply atomic operations to data not declared to be atomic, using code such as

int x; reinterpret_cast<atomic<int>&>(x).fetch_add(1);

This would clearly fail if the representations of atomic and int differ, or if their alignments differ. But I know that this is not an issue on platforms I care about. And, in practice, I can easily test for a problem by checking at compile time that sizes and alignments match.

不过,在这种情况下对我来说没问题,因为我在同一台机器上使用共享内存并在两个不同的进程中转换指针将“获取”相同的位置。但是,文章指出编译器可能不会将转换后的指针视为指向原子类型的指针:

However this is not guaranteed to be reliable, even on platforms on which one might expect it to work, since it may confuse type-based alias analysis in the compiler. A compiler may assume that an int is not also accessed as an atomic<int>. (See 3.10, [Basic.lval], last paragraph.)

欢迎任何意见!

最佳答案

C++ 标准本身不关心多进程,并且在多线程环境之外不提供任何保证。但是,标准确实 recommend无锁原子的实现可以跨进程使用,这在大多数实际实现中都是如此。这个答案将假设原子在进程和线程中的行为或多或少相同。

第一个解决方案需要 C++20 atomic_ref

void* shared_mem = /* something */

auto p1 = new (shared_mem) int; // For creating the shared object
auto p2 = (int*)shared_mem; // For getting the shared object

std::atomic_ref<int> i{p2}; // Use i as if atomic<int>

您需要确保共享 intstd::atomic_ref<int>::required_alignment结盟;通常与 sizeof(int) 相同.通常你会使用 alignas()在结构成员或变量上,但在共享内存中,布局由您决定(相对于已知页面边界)。

这可以防止共享内存中存在不透明的原子类型,从而使您可以精确控制其中的内容。


C++20 之前的解决方案是

auto p1 = new (shared_mem) atomic<int>;  // For creating the shared object
auto p2 = (atomic<int>*)shared_mem; // For getting the shared object

auto& i = *p2;

或使用 C11 atomic_load atomic_store

_Atomic int* i = (_Atomic int*)shared_mem;
atomic_store(i, 42);
int i2 = atomic_load(i);

此处对齐要求相同,alignof(std::atomic<int>)_Alignof(atomic_int) .

关于c++ - 两个不同的进程在同一地址上有 2 个 std::atomic 变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51229208/

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