繁体   English   中英

可以使用跨语言平台的 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 作者是一个C++程序,读者是一个Python程序。 工作大致是这样的:

  • C++ 代码在原子操作中更新counter
  • Python代码读取counter并具有一致的内存视图(最终一致性完全可以接受)
  • 没有实施锁来实现这一点

在 C++ 语言中,有原子获取/更新操作可以实现这一点并保证内存一致性,我相信在 Python 中也是如此。

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

有没有一种方法可以在不涉及实现低级锁的情况下实现跨语言的共享内存的一致视图?

有没有一种方法可以在不涉及实现低级锁的情况下实现跨语言的共享内存的一致视图?

不,不是一般的。

首先,我想说这与语言无关,而更多地与实际平台、架构、实现或操作系统有关。

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

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

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

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

System V 将是为这种交换而设计的 API,但由于 AFAIK 它没有原子的抽象或锁定较少的抽象,因此即使 System V 上下文不在标题中,答案仍然是否定的。

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

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

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

是的,使用atomics库以及合适的共享内存库(例如mmapshared_memory )。
此示例假设您的原子整数位于共享内存段的前 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 (并正确管理其生命周期)。

注意:我是这个库的作者

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM