是否可以跨语言平台使用 System V 共享内存在 4 字节 int 上实现无锁原子写/一致读操作?

Can a lock-free atomic write / consistent read operation be achieved on a 4 byte int using System V shared memory across language platforms?

我想在 System V 共享内存中实现一个无锁 counter,一个 4 字节 int。 writer是一个C++程序,reader是一个Python程序。大致是这样工作的:

在 C++ 语言中有原子 get/update 操作允许这样做并保证内存一致性,我相信在 Python 中也是如此。

但是,据我了解,C++ 中关于原子操作的假设不一定适用于用另一种语言和编译器编写和编译的代码。

Is there a way to achieve a consistent view of shared memory across languages that doesn't involve implementing low level locks?

Is there a way to achieve a consistent view of shared memory across languages that doesn't involve implementing low level locks?

没有,一般不会。

首先我要说这与语言无关,而与实际平台、体系结构、实现或操作系统有关。

因为语言差异很大,以Python为例:它没有直接访问内存的语言本地方式,或者可以说是低级方式。然而,它的一些实现确实提供了自己的 API。像 C、C++ 或 Rust 那样,用于这种低级使用的语言具有抽象。但是这些抽象的实现方式往往完全不同,因为它们通常取决于代码在何处 运行、解释或编译。某些体系结构的整数是大端,在大多数情况下,如 x86 或 arm,它是小端。操作系统也有发言权,例如内存的使用和抽象。

虽然许多语言都有线性内存的共同抽象,但它在原子性方面变得更加混乱:C++ 编译器可以生成机器代码,即检查 CPU 运行 是否正确的程序集支持新的奇特原子整数指令并使用它们或退回到经常支持的原子标志加上整数。它可以仅依赖于操作系统、自旋锁或由 POSIX、SystemV、Linux、Windows 定义的标准化 API,如果代码具有 运行在操作系统管理的环境中 .

对于非命令式语言,它变得更加混乱。

因此,为了在语言之间交换数据,这些语言的实现必须使用一些通用的交换。例如,他们可以尝试直接通过共享内存来做到这一点。这被称为应用程序二进制接口 (ABI),因为内存抽象至少对它们来说是先验的。或者操作系统或架构甚至可能标准化这些东西,甚至支持 APIs.

System V 将是为这种交换而设计的 API,但由于 AFAIK 它没有原子抽象或无锁抽象,答案是否定的,即使使用 System V标题的上下文。

我要对 Superlokkus 的一些断言提出异议。

mmap 原语在 C++ 和 Python 中均可用。该原语为您提供了两个进程共享的物理页面中的内存。不同的虚拟地址,相同的物理内存页。一个进程的更改可以立即被另一个进程看到。这就是它必须工作的方式。它在硬件级别运行。抽象无关紧要。

现在,这并不意味着您可以获得这些更改的通知。如果您在循环中轮询(大概是一个在检查之间休眠的友好循环),那么您将在下次检查时看到更改。

是的,使用 atomics 库以及合适的共享内存库(例如 mmapshared_memory)。
此示例假定您的 atomic int 位于共享内存段的前 4 个字节中。

from atomics import atomicview, MemoryOrder, INT
from multiprocessing import shared_memory


# connect to existing shared memory segment
shmem = SharedMemory(name="test_shmem")

# get buf corresponding to "atomic" region
buf = shmem.buf[:4]

# atomically read from buffer
with atomicview(buffer=buf, atype=INT) as a:
    value = a.load(order=MemoryOrder.ACQUIRE)

# print our value
print(value)

# del our buf object (or shmem.close() will complain)
del buf

# close our shared memory handle
shmem.close()

我们可以在这里使用ACQUIRE内存顺序而不是默认的SEQ_CST

atomicview 只能通过 with 语句创建和使用,因此您需要手动保留 buf(并正确管理其生命周期)。

注意:我是这个库的作者