为什么从不同进程读取文件时出现竞争状况?

时间:2019-01-13 18:09:20

标签: python multiprocessing

我正在尝试读取包含6000行相同长度的大文本文件。 可以通过不同的过程访问文件,并且我获取了互斥量以防止出现竞争情况。但是输出包含部分读取的行:

58 '444444444444444444444444444444444444444444444444444444444\n'
58 '333333333333333333333333333333333333333333333333333333333\n'
46 '444444444444444444444444442222222222222222222\n'
58 '444444444444444444444444444444444444444444444444444444444\n'

我试图运行的代码:

import multiprocessing as mp

class Loader:
    def __init__(self, path):
        self.lock = mp.Lock()
        self.file = open(path, 'r')

    def read(self):
        with self.lock:
            try:
                line = next(self.file)
                print(len(line), repr(line))
            except StopIteration:
                return False
        return True


def worker(loader):
    while loader.read():
        pass

if __name__ == '__main__':
    loader = Loader('./data.txt')

    workers = []
    for i in range(4):
        w = mp.Process(target=worker, args=(loader,))
        w.daemon = True
        w.start()
        workers.append(w)

    for w in workers:
        w.join()

首先,我希望将file描述符复制到另一个进程时会出错,但是程序已启动,并且所有进程都可以从该文件读取。 但是种族条件令我沮丧,为什么每个过程都不​​读整行?

1 个答案:

答案 0 :(得分:1)

您不会复制文件对象,因为您没有复制任何内容(通常意义上)。您正在使用(Unix)默认的fork技术,因此每个进程都会继承(打开时的复制版本)相同的打开文件。

因此(如VPfB所指出的),每个进程都会执行自己的缓冲,但是底层的打开文件描述是共享的,并且包含文件偏移量。如果您在开始处理之前先读过一个字符,您会发现它们在分开(和混合行)之前都报告文件的相同前缀。