当前位置:   article > 正文

Python基础_多进程数据共享_python 多进程共享数据

python 多进程共享数据

一、多进程数据共享

Python中,多进程之间的数据共享是一个复杂的主题,因为每个进程都有自己的内存空间和独立的Python解释器实例。这意味着它们不能直接共享数据,就像线程那样。但是,Python提供了几种方法来间接地实现多进程之间的数据共享。

二、使用multiprocessing.Manager对象

multiprocessing模块提供了一个Manager对象,它可以让创建可以在多个进程之间共享的数据结构,如列表和字典。Manager对象背后实际上是通过进程间通信(IPC)实现的。

**使用示例:**创建可以在多个进程之间共享的字典

from multiprocessing import Process, Manager

def func(d, i):
    d[i] = i * i

if __name__ == '__main__':
    with Manager() as manager:
        d = manager.dict()
        processes = [Process(target=func, args=(d, i)) for i in range(10)]
        for p in processes:
            p.start()
        for p in processes:
            p.join()
        print(d)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
'
运行
# 执行结果
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
  • 1
  • 2
'
运行

三、使用multiprocessing.Value和multiprocessing.Array

这两个类允许创建可以在多个进程之间共享的值和数组。

它们是基于ctypes模块的,这意味着可以创建不同类型的数据结构(如整数、浮点数数组等)。

**使用示例:**使用共享类ValueArray

from multiprocessing import Process, Value, Array

def func(n, a):
    n.value = 3.1415927
    for i in range(len(a)):
        a[i] **= 2

if __name__ == '__main__':
    num = Value('d', 0.0)
    arr = Array('i', range(10))

    p = Process(target=func, args=(num, arr))
    p.start()
    p.join()

    print(num.value)
    print(arr[:])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
'
运行
# 执行结果
3.1415927
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
  • 1
  • 2
  • 3
'
运行

四、使用管道和队列

尽管不是真正的“共享”数据,但multiprocessing.Pipemultiprocessing.Queue提供了进程间通信的机制。

这些对象可以在进程之间传递数据,从而实现某种形式的数据“共享”。

使用示例:Queue数据共享

from multiprocessing import Process, Queue

def func(q, i):
    q.put('hello {} times'.format(i))

if __name__ == '__main__':
    q = Queue()
    plist= [Process(target=func, args=(q, i)) for i in range(3)]
    for p in plist:
        p.start()
        p.join()
    while not q.empty():
        tmpVal = q.get()
        print(tmpVal)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
'
运行
# 执行结果
hello 0 times
hello 1 times
hello 2 times
  • 1
  • 2
  • 3
  • 4

五、使用共享内存

在某些情况下,可能需要直接使用操作系统的共享内存机制。可以通过multiprocessing.RawValuemultiprocessing.RawArray类来实现,但它们提供了更低的抽象级别,需要谨慎使用。

multiprocessing.RawValuemultiprocessing.RawArray 用于创建可以直接在多个进程之间共享的内存区域。

ManagerValueArray 不同,RawValueRawArray 不提供任何锁机制,因此它们更快,但同时也需要程序员负责同步以避免数据竞争。

使用 RawValueRawArray 示例:

from multiprocessing import Process, RawValue, RawArray, Lock

# 使用RawValue
def process_with_raw_value(value, lock):
    with lock:
        for _ in range(10000):  # 假设有很多次写操作
            value.value += 1

# 使用RawArray
def process_with_raw_array(arr, lock):
    with lock:
        for i in range(len(arr)):
            arr[i] **= 2  # 对数组中的每个元素进行平方操作

if __name__ == '__main__':
    # 创建一个RawValue对象,初始值为0,类型为'i'(整数)
    lock = Lock()  # 创建一个锁对象用于同步
    shared_value = RawValue('i', 0)

    # 创建一个RawArray对象,包含5个整数元素
    shared_array = RawArray('i', [1, 2, 3, 4, 5])

    # 创建并启动两个进程,分别处理RawValue和RawArray
    p1 = Process(target=process_with_raw_value, args=(shared_value, lock))
    p2 = Process(target=process_with_raw_array, args=(shared_array, lock))

    p1.start()
    p2.start()

    p1.join()
    p2.join()

    # 由于RawValue和RawArray不提供同步机制,们需要使用锁来确保数据一致性
    with lock:
        print("Shared value:", shared_value.value)  # 输出共享值的最终结果
        print("Shared array:", shared_array[:])     # 输出共享数组的最终结果
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
'
运行
# 执行结果
Shared value: 10000
Shared array: [1, 4, 9, 16, 25]
  • 1
  • 2
  • 3

注意:尽管 RawValueRawArray 提供了更高的性能和更灵活的数据共享方式,但它们也更难正确使用,因为需要程序员自己处理所有的同步问题。在大多数情况下,如果不需要这么底层的控制,使用 ManagerValueArray 会更简单和安全。

六、注意事项

由于GIL(全局解释器锁)的存在,共享数据在并发修改时可能会导致不可预知的行为。

因此,在共享数据时,请务必确保正确地同步进程,以避免数据竞争和不一致。


may the odds be ever in your favor ~

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/寸_铁/article/detail/798770
推荐阅读
相关标签
  

闽ICP备14008679号