Multithreading 如何损坏从多个线程写入的文件?

Multithreading 如何损坏从多个线程写入的文件?,multithreading,file,python-3.x,python-multithreading,Multithreading,File,Python 3.x,Python Multithreading,我正在编写一个函数来将数据保存到文件中。可以使用相同的参数(相同的数据、相同的文件)同时从多个线程或进程调用它。这是一个我无法避免的场景,因此我正在编写单元测试以确保它不会导致数据损坏 为了信任我的单元测试,我想测试它们是否在编写糟糕的函数时失败。我没有成功,我的文件始终包含预期的数据 这里有一种重现(缺少)问题的方法。文件test.txt始终包含内容 import io import threading # 1,000,000 lines: Test #0, Test #1, ..., Te

我正在编写一个函数来将数据保存到文件中。可以使用相同的参数(相同的数据、相同的文件)同时从多个线程或进程调用它。这是一个我无法避免的场景,因此我正在编写单元测试以确保它不会导致数据损坏

为了信任我的单元测试,我想测试它们是否在编写糟糕的函数时失败。我没有成功,我的文件始终包含预期的数据

这里有一种重现(缺少)问题的方法。文件
test.txt
始终包含
内容

import io
import threading

# 1,000,000 lines: Test #0, Test #1, ..., Test #999999. About 13Mb.
CONTENT = ''.join(['Test #' + str(i) + "\n" for i in range(1000000)]).encode()

# Thread to write CONTENT to test.txt
class WriteThread(threading.Thread):
    def run(self):
        stream = io.BytesIO(CONTENT)
        with open('test.txt', 'wb') as f:
            for buffer in iter(lambda: stream.read(), b''):
                f.write(buffer)

# Run 100 write threads in parallel
threads = []
for i in range(100):
    threads.append(WriteThread())
for t in threads:
    t.start()
for t in threads:
    t.join()

我做错了吗?我幸运吗?这是我应该依赖的行为吗?

相当于
f.write(stream.read())
,因为你实际上没有读块,你只是读了整个该死的文件,第二次调用时什么都没有得到。我无法理解您认为您在测试什么,因为将完全相同的内容写入独立打开的句柄到同一个文件只会填充和截断同一个文件,并以相同的数据结束。@marcv81:每次使用
'w'
打开句柄时,它都会截断该文件。因此,无论最后发生哪一次写入,都将(可能)决定文件内容,除非在最后一次截断之后安排了其他写入…@marcv81:如果您正在写入位和块,则可能会出现一些奇怪的行为,具体取决于系统。每个使用
w
打开的
都会截断文件,但是已经写入内容的线程的文件指针可能会继续指向很远的地方,在该点写入可能会强制前面的数据用零填充。如果所有线程都写入相同的数据,当所有线程都稳定下来时,您可能不会注意到任何奇怪的事情(不保证),但在运行时,文件中可能会稀疏地填充由零初始化间隔分隔的块。@ShadowRanger:您想要
os.fsync()
甚至
os.fdatasync()
os.sync()
可能会关闭并摆弄一些网络安装的文件系统,这些文件系统与您试图同步的文件无关。@marcv81:不,如果您使用的是Python 3.3或更高版本<当目标名称已经存在时,code>os.rename
在Windows和Linux之间没有一致的语义,而
os.replace
保证了覆盖行为。同样的分区要求就是为什么我提到将临时文件放在与“real”文件相同的目录中,因为(应该)保证tempfile和real文件在同一个分区上。