python - 我怎样才能使 python mmap 赋值原子化?

标签 python

如何使 python mmap 赋值成为原子操作?这里没有提到原子:https://docs.python.org/3.0/library/mmap.html

huge_list1 = [888 for _ in range(100000000)]
huge_list2 = [9999 for _ in huge_list1]
b1 = struct.pack("100000000I", *huge_list1)
b2 = struct.pack("100000000I", *huge_list1)

f = open('mmp', 'wb')
f.write(b1)
f.close()
f = open('mmp', 'r+')
m = mmap.mmap(f.fileno(), 0)
m[:]=b2

我立即在另一个进程中执行以下代码

f = open('mmp', 'r')
m = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
mm = m[:]
l = struct.unpack("100000000I", mm)
set(l)

然后我看到 {888, 9999}

这意味着 mmap 不是原子的。无论如何让它成为原子?

最佳答案

一般来说,你不能。文件写入一开始就不是原子的,无论是通过 mmap 还是 write 完成。一些文件系统,例如 Tahoe-LAFS,确实有一个文件放置操作,但即使在那里它也是一个已知完成的问题,而不是原子操作( block 是单独存储的)。文件内容更新的原子性通常通过三种方法完成:

  1. 使用 rename调用,您可以确定名称指向旧文件或新文件(Python 的 Path.replace 可能更清楚)。这是例如使用的方法maildir .

  2. 使用 file locks .这些通常是协作的,这意味着访问该文件的所有程序必须一致地使用相同的锁定方法。有时这是不可能的,例如在某些网络文件系统中。由于这种不一致,其他锁定方法如 lock files也被使用 - 因此“相同方法”的要求。

  3. 使用由于底层架构(例如磁盘扇区)而具有原子性的较小访问。这是完成的,例如在 SQLite's journal headers .值得注意的是,阈值与 mmap 不同,因为内存页面本身可能是共享的,从而允许更精细的原子访问粒度(可能是 CPU 字大小或单字节)。

这个话题相当复杂。将任何这些同步方法与 mmap 结合的关键是 mmap.flush .

关于python - 我怎样才能使 python mmap 赋值原子化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49431056/

相关文章:

python - QWebview 的 Dymo 标签打印机?

python - 从 io.BytesIO 流打开 sqlite3 数据库?

python - 使用 ABCMeta 和 EnumMeta 抽象枚举类

python - 使用 Scikit-Learn 生成高维数据集

python - 如何分割 Pandas 数据框

python - 在 Windows 上安装 Python Fabric

python - itertools 无法将 numpy 整数识别为 Python 3.6 上的有效输入

python - 后继者和前任者 - 二叉搜索树 (Python)

python - QPython无法安装requests模块

python - 计算均方误差返回 y_true 和 y_pred 有不同数量的输出 (1!=10)