进程和线程之间共享和更新列表

Posted

技术标签:

【中文标题】进程和线程之间共享和更新列表【英文标题】:Sharing and Updating List between Processes and Threads 【发布时间】:2022-01-16 14:48:36 【问题描述】:

尝试在主进程 - 主线程和子进程 - 子线程之间共享和更新列表。目前看来,主进程和主线程共享一个列表副本的更新,而子进程和子线程共享另一个列表副本。我原以为经理会允许在所有 4 人之间共享列表。非常感谢任何帮助。

代码:

from multiprocessing import Process, Manager
import time
import threading

def main_thread(l):
    while True:
        l[0][5] += 1
        print("main_thread:", l)
        time.sleep(6)

def sub_thread(l):
    while True:
        l[1][5] += 1
        print("sub_thread:", l)
        time.sleep(7)

def sub_process(l):
    #create a sub_thread to update l[1][5]
    trading_thread = threading.Thread(target=sub_thread, args=(l,))
    trading_thread.start()
    time.sleep(1)
    while True:
        l[0][6] += 1
        print("sub_process:", l)
        time.sleep(9)

def main_process():
    #create a thread to increment l[0][5]
    trading_thread = threading.Thread(target=main_thread, args=(l,))
    trading_thread.start()
    time.sleep(1)
    #Create a sub_process to start a sub_process and increment l[0][6]
    p = Process(target=sub_process, args=(l,))
    p.start()
    time.sleep(1)
    #I need this while loop to run as well:
    while True:
        l[0][7] += 1
        print("main_process: ", l)
        time.sleep(8)
    p.join()    #this could be a problem - we never get to this because sub process is never supposed to finish,
                #I tried to put this before the 'While' loop above but then the loop never gets triggered.

if __name__ == '__main__':
    manager = Manager()
    l = manager.list()
    l = [['LACE', 1639144800000, 1.157857245, '9:00 December 10, 2021', 'True', 0, 0, 0],
        ['ARKER', 1639109835404, 0.0, '10:00 December 10, 2021', 'True', 0, 0, 0]]
    main_process()

输出:

main_thread: [['LACE', 1639144800000, 1.157857245, '9:00 December 10, 2021', 'True', 1, 0, 0], ['ARKER', 1639109835404, 0.0, '10:00 December 10, 2021', 'True', 0, 0, 0]]
sub_thread: [['LACE', 1639144800000, 1.157857245, '9:00 December 10, 2021', 'True', 1, 0, 0], ['ARKER', 1639109835404, 0.0, '10:00 December 10, 2021', 'True', 1, 0, 0]]
main_process:  [['LACE', 1639144800000, 1.157857245, '9:00 December 10, 2021', 'True', 1, 1, 0], ['ARKER', 1639109835404, 0.0, '10:00 December 10, 2021', 'True', 0, 0, 0]]
sub_process: [['LACE', 1639144800000, 1.157857245, '9:00 December 10, 2021', 'True', 1, 0, 0], ['ARKER', 1639109835404, 0.0, '10:00 December 10, 2021', 'True', 1, 1, 0]]
main_thread: [['LACE', 1639144800000, 1.157857245, '9:00 December 10, 2021', 'True', 2, 1, 0], ['ARKER', 1639109835404, 0.0, '10:00 December 10, 2021', 'True', 0, 0, 0]]
sub_thread: [['LACE', 1639144800000, 1.157857245, '9:00 December 10, 2021', 'True', 1, 0, 0], ['ARKER', 1639109835404, 0.0, '10:00 December 10, 2021', 'True', 2, 1, 0]]
main_process:  [['LACE', 1639144800000, 1.157857245, '9:00 December 10, 2021', 'True', 2, 2, 0], ['ARKER', 1639109835404, 0.0, '10:00 December 10, 2021', 'True', 0, 0, 0]]
sub_process: [['LACE', 1639144800000, 1.157857245, '9:00 December 10, 2021', 'True', 1, 0, 0], ['ARKER', 1639109835404, 0.0, '10:00 December 10, 2021', 'True', 2, 2, 0]]
main_thread: [['LACE', 1639144800000, 1.157857245, '9:00 December 10, 2021', 'True', 3, 2, 0], ['ARKER', 1639109835404, 0.0, '10:00 December 10, 2021', 'True', 0, 0, 0]]
sub_thread: [['LACE', 1639144800000, 1.157857245, '9:00 December 10, 2021', 'True', 1, 0, 0], ['ARKER', 1639109835404, 0.0, '10:00 December 10, 2021', 'True', 3, 2, 0]]
main_thread: [['LACE', 1639144800000, 1.157857245, '9:00 December 10, 2021', 'True', 4, 2, 0], ['ARKER', 1639109835404, 0.0, '10:00 December 10, 2021', 'True', 0, 0, 0]]
main_process:  [['LACE', 1639144800000, 1.157857245, '9:00 December 10, 2021', 'True', 4, 3, 0], ['ARKER', 1639109835404, 0.0, '10:00 December 10, 2021', 'True', 0, 0, 0]]
sub_process: [['LACE', 1639144800000, 1.157857245, '9:00 December 10, 2021', 'True', 1, 0, 0], ['ARKER', 1639109835404, 0.0, '10:00 December 10, 2021', 'True', 3, 3, 0]]
sub_thread: [['LACE', 1639144800000, 1.157857245, '9:00 December 10, 2021', 'True', 1, 0, 0], ['ARKER', 1639109835404, 0.0, '10:00 December 10, 2021', 'True', 4, 3, 0]]

【问题讨论】:

【参考方案1】:

当你这样做时:

    l = manager.list()
    l = [['LACE', 1639144800000, 1.157857245, '9:00 December 10, 2021', 'True', 0, 0, 0],
        ['ARKER', 1639109835404, 0.0, '10:00 December 10, 2021', 'True', 0, 0, 0]]

第二个赋值删除第一个赋值并用一个普通的旧 Python 列表替换它。这样做:

    l = manager.list(
        [['LACE', 1639144800000, 1.157857245, '9:00 December 10, 2021', 'True', 0, 0, 0],
        ['ARKER', 1639109835404, 0.0, '10:00 December 10, 2021', 'True', 0, 0, 0]]
    )

跟进

另一个问题比较棘手。该语句确实将第一个列表转换为托管列表。如果您将线程更改为l.append(7),您会看到列表确实增长了。但是,INSIDE 列表仍然是普通的列表对象,它们不是共享的。所以,l 是托管列表,但 l[0] 不是。

你可以通过这样做来解决这个问题

    l = manager.list([
        manager.list(['LACE', 1639144800000, 1.157857245, '9:00 December 10, 2021', 'True', 0, 0, 0]),
        manager.list(['ARKER', 1639109835404, 0.0, '10:00 December 10, 2021', 'True', 0, 0, 0])
    ])

但如果你这样做,你将不得不以不同的方式打印它们:

    print("sub process:", l[0], l[1])

一般来说,像这样共享数据结构并不是一个好主意。你知道实施吗? Manager() 创建另一个新进程,这是一个 TCP 服务器,它接受来自子进程的更新并将更新广播出去。它比使用常规列表慢 100 倍。

没有像这样在进程之间全局共享数据的好方法。只要您了解限制,您可以在共享内存中尝试Array。线程可以共享一个全局变量,但进程确实需要彼此独立。您可以使用Queue 将结果传回母舰,但像这样更新共享数据结构并不实际。

【讨论】:

我刚试过这个,现在列表根本没有从进程或线程更新。它只是打印与定义相同的嵌套列表。

以上是关于进程和线程之间共享和更新列表的主要内容,如果未能解决你的问题,请参考以下文章

多线程和多进程的区别

进程线程js单线程

Java 线程系列Java线程之间的共享和协作

Java 线程系列Java线程之间的共享和协作

Python 多进程和多线程 的使用

进程和线程的区别