为什么我在从不同的过程中读取文件时遇到竞争条件?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么我在从不同的过程中读取文件时遇到竞争条件?相关的知识,希望对你有一定的参考价值。

我正在尝试阅读包含6000行相同长度的大文本文件。文件可以通过不同的过程访问,我获取互斥锁以防止竞争条件。但输出包含部分读取行:

58 '444444444444444444444444444444444444444444444444444444444
'
58 '333333333333333333333333333333333333333333333333333333333
'
46 '444444444444444444444444442222222222222222222
'
58 '444444444444444444444444444444444444444444444444444444444
'

代码我试图运行:

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描述符复制到另一个进程时会出错,但程序已启动,所有进程都可以从该文件中读取。但是竞争条件让我灰心丧气,为什么每个过程都不​​读全线?

答案

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

所以(正如VPfB指出的那样)每个进程都有自己的缓冲,但底层的打开文件描述是共享的,并且包含文件偏移量。如果您在开始进程之前读取了一个字符,您会看到它们在发散之前报告了相同的文件前缀(并混合了行)。

以上是关于为什么我在从不同的过程中读取文件时遇到竞争条件?的主要内容,如果未能解决你的问题,请参考以下文章

为啥这里举例说明在 LINUX 中使用命名管道 -FIFO 的程序会遇到竞争条件?

促进进程间竞争条件预防

当多个进程尝试同时写入然后从文件中读取时,如何防止竞争条件

GDB 防止错误

C ++将文本文件中的数字读取到数组中

在从不同模式调用过程时如何在 oracle 中查找所有嵌套的依赖对象