如何使python mmap赋值原子化?{这里什么都没说}
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
我立即在另一个进程中执行以下代码
^{pr2}$然后我看到{8889999}
这意味着mmap不是原子的。不管怎样让它原子化?
一般来说,你不能。文件写入不是原子的,不管是通过mmap还是write。有些文件系统,如tahoelafs,确实有一个文件放入操作,但即使在那里,它也是已知完成的问题,而不是原子操作(块是单独存储的)。文件内容更新的原子性通常有三种方法:
使用rename调用,可以确保名称指向旧文件或新文件(Python的Path.replace可能更清楚)。这是在maildir中使用的方法。
使用file locks。这些都是一般协作的,这意味着访问文件的所有程序必须一致地使用相同的锁定方法。有时这是不可能的,例如在一些网络文件系统中。由于这种不一致性,还使用了其他锁方法,如lock files,因此需要“相同的方法”。
使用由于底层架构(如磁盘扇区)而具有原子性的较小访问。这是在SQLite's journal headers中完成的。值得注意的是,这个阈值与mmap不同,因为内存页本身可能是共享的,允许原子访问的粒度更细(可能是CPU字大小或单字节)。
这个话题相当复杂。将这些同步方法与mmap结合的关键是mmap.flush。在
我不认为这是一个
mmap
问题,我敢打赌这是因为f.close()
保证Python已经将数据发送到底层操作系统的缓冲区,但这并不意味着它已经被实际写入。然后当您再次打开它,并将句柄交给mmap
,您仍然在对缓冲区进行操作。在您可以在关闭文件之前尝试同步缓冲区,以确保所有内容都已写入:
或者更好,只是为了让Python在发生错误时干净地处理关闭:
^{pr2}$尽管
os.fsync()
不是100%的保证,但从底层的fsync()
手册页:但我敢打赌,在非常罕见的边缘情况下,它不能满足你的需要。在
相关问题 更多 >
编程相关推荐