首页 > 编程问答 >使用 Python 中的多处理防止共享内存中的数据损坏?

使用 Python 中的多处理防止共享内存中的数据损坏?

时间:2024-07-29 14:59:47浏览次数:8  
标签:python multiprocessing data-integrity

我目前正在开发一个多处理 Python 程序,其中每个进程将其索引作为连续的 4 字节整数写入共享内存。并且有一个读取器可以在没有任何锁的情况下读取其他进程的索引。因为我没有使用任何同步原语,所以我担心读取器进程可能会由于逐字节写入内存而读取损坏的数据(例如,一个索引的前 2 个字节和另一个索引的最后 2 个字节)。|| |阅读以前的索引对我来说不是问题;我只需要确保读取索引在历史上有效。

我观察到,在 macOS 上,不会发生此问题(可能是由于 Python 或 macOS 特定的行为)。但是,该程序也需要在其他操作系统(例如 Windows 和 Ubuntu)上运行。

我在下面创建了一个小示例。

任何确保数据完整性的建议或示例将不胜感激!

import time
import random
import struct
import multiprocessing
from multiprocessing import shared_memory

def writer(rank, shared_memory):
    index = 0
    while True:
        byte_array = struct.pack("i", index)
        shared_memory.buf[rank * 4: rank * 4 + 4] = byte_array
        index += 1
        time.sleep(random.random())

def reader(shared_memory, size):
    while True:
        indexes = struct.unpack(f"{size}i", shared_memory.buf[:size*4])
        print(f"Read indexes: {indexes}")
        time.sleep(1)

if __name__ == "__main__":
    size = 10
    shared_memory = shared_memory.SharedMemory(
            create=True, size= 4 * size
        )
    
    ctx = multiprocessing.get_context("spawn")

    processes = []
    for i in range(size):
        p = ctx.Process(target=writer, args=(i, shared_memory))
        processes.append(p)
        p.start()

    reader_process = multiprocessing.Process(target=reader, args=(shared_memory, size))
    reader_process.start()

    for p in processes:
        p.join()
    reader_process.join()

Any advice or examples to ensure data integrity would be appreciated!


你绝对正确地担心在没有同步原语的情况下从共享内存中读取数据会出现数据损坏。即使在 macOS 上一切看起来正常运行,你的代码也存在竞争条件,最终会在 macOS 或任何其他操作系统上导致错误的读取。

问题在于,读取器进程可以捕获写入器进程只写入了其 4 字节索引中的一部分,从而导致读取的值损坏。

为了解决这个问题,你需要在写入器和读取器之间引入同步机制。以下是如何使用 multiprocessing.Lock 来确保数据完整性:

import time
import random
import struct
import multiprocessing
from multiprocessing import shared_memory

def writer(rank, shared_memory, lock):
    index = 0
    while True:
        byte_array = struct.pack("i", index)
        with lock:  # Acquire lock before writing
            shared_memory.buf[rank * 4: rank * 4 + 4] = byte_array
        index += 1
        time.sleep(random.random())

def reader(shared_memory, size, lock):
    while True:
        with lock:  # Acquire lock before reading
            indexes = struct.unpack(f"{size}i", shared_memory.buf[:size*4])
        print(f"Read indexes: {indexes}")
        time.sleep(1)

if __name__ == "__main__":
    size = 10
    shared_memory = shared_memory.SharedMemory(create=True, size= 4 * size)
    lock = multiprocessing.Lock()  # Create a lock

    ctx = multiprocessing.get_context("spawn")

    processes = []
    for i in range(size):
        p = ctx.Process(target=writer, args=(i, shared_memory, lock))  # Pass the lock to the writer
        processes.append(p)
        p.start()

    reader_process = multiprocessing.Process(target=reader, args=(shared_memory, size, lock))  # Pass the lock to the reader
    reader_process.start()

    for p in processes:
        p.join()
    reader_process.join()

在这个修改后的代码中:

  1. 我们创建了一个 multiprocessing.Lock 对象,并在写入器和读取器进程之间共享它。
  2. 写入器进程在更新共享内存之前获取锁,并在完成后释放锁。
  3. 读取器进程在从共享内存读取数据之前获取锁,并在完成后释放锁。

这可以确保读取器进程永远不会在写入器进程更新 4 字节索引的过程中读取共享内存,从而防止出现数据损坏并保持数据完整性。

还应注意的是,虽然这种基于锁的方法可以有效地防止数据损坏,但它可能会给你的代码带来一些开销并影响性能,尤其是在争用锁的情况下。如果你需要一个性能更高的解决方案,你可能需要研究其他方法,例如无锁数据结构或原子操作,但这些方法的实现可能更加复杂。

标签:python,multiprocessing,data-integrity
From: 78805755

相关文章

  • Python如何统治AI世界?一文读懂它的优势与挑战
    一、Python语言介绍1.1Python语言概述Python是一种由GuidovanRossum于1991年首次发布的高级编程语言。其设计理念强调代码的可读性和简洁性,使其成为了许多开发者的首选语言。Python的语法简洁直观,采用了缩进来定义代码块,这与其他使用花括号或关键词的编程语言不同。Python......
  • 找到一种方法将program1的输出作为python中program2的输入发送
    有人可以帮我找到一种方法将program1的输出作为python中的program2的输入发送将其保存为.csv文件不会对我有帮助,因为该程序应该尽快执行这些任务。因此我正在寻找一种方法将程序1的终端输出直接发送到程序2在Python中,可以使用子进程模块将一个程序的输出发送到另一个程......
  • 同时运行多个Python程序的最佳方法
    我有一个python程序,我想同时运行多个具有不同参数的实例。这些实例彼此之间不进行通信。在单独的终端中运行每个实例太乏味了。我考虑使用多处理模块将每个实例作为单独的进程运行,但是我希望能够随时停止和重新启动某些单独的实例,而不会中断其他正在运行的实例。是否有任何流程......
  • 替换 Python 数据框中包含值的 <
    我有一个数据框,在某些列中存在诸如“<0.5、<10、<100”等值。如果值仅包含“<”,我想将所有这些值替换为0。我该怎么做?我对Python比较陌生。尝试使用pd.DataFrame.replace()。importpandasaspd#创建示例数据框df=pd.DataFrame({'A':['<0.5','<10',15,20],......
  • 基于funasr+pyaudio实现电脑本地麦克风实时语音识别项目语音转文本python实现
    【框架地址】https://github.com/modelscope/FunASR【简单介绍】FunASR是一个功能全面的语音识别工具包,支持多种预训练模型的推理和微调,提供高精度和高效能的语音识别服务。结合PyAudio库,可以实现电脑本地麦克风实时语音识别项目。该项目首先通过PyAudio库捕获麦克风输入的......
  • 从Python中的数据框中删除不必要的数据
    所以我这里有一个dat文件,我正在使用Python来读取它。在整个文件中,有一些不必要的行,例如BEGIN等,而我真正想开始阅读的部分是从数据帧开始。因此,我想检查在Python中执行此操作的最佳方法是什么,并且只阅读数据框何时开始?谢谢!以下是使用Python从数据......
  • Python拟合曲线
    拟合曲线多项式拟合np.ployfit(x,y,deg)importmatplotlib.pyplotaspltimportnumpyasnpx=[1,1.5,2,2.5,3,3.5,4,4.5,5,5.5,6,6.5,7,7.5,8]y=[33.40,79.50,122.65,159.05,189.15,214.15,238.65,252.2,267.55,280.50,296.65,301.65,310.......
  • 12个Python数据类型转换实战演练
    文末赠免费精品编程资料~~在Python编程中,数据类型转换是处理数据时必不可少的技能。掌握如何灵活地在不同类型之间转换,能让你的代码更加高效和灵活。下面,我们将通过一系列实战演练,学习并实践12种常见的Python数据类型转换。1.整数转字符串实战案例:将年龄转换为字符串......
  • Python全套教程,小白零基础入门必备!
    Python是一种语法简单、功能强大的编程语言,它注重的是如何高效解决问题。【教程领取方式在文末!!】正是这种简单实用的特性,让Python成为近年来最热门的编程语言之一。Python具有广泛的应用场景,包括:Web开发、数据分析、机器学习、网络爬虫、人工智能、量化交易等众多领......
  • BP神经网络及其Python和MATLAB实现预测
    BP神经网络及其Python和MATLAB实现预测引言BP神经网络(BackPropagationNeuralNetwork),即反向传播神经网络,是一种通过反向传播算法进行监督学习的多层前馈网络。这种网络能够通过不断地调整和改变神经元的连接权重,达到对特定任务的学习和优化。由于其高度的灵活性和适应性......