### 探究Python多进程编程下线程之间变量的共享问题 #### 一、问题背景与分析 在Python中,由于全局解释器锁(Global Interpreter Lock, GIL)的存在,多线程并不能实现真正的并行执行,而是通过线程调度在多个线程间切换执行。因此,在Python中实现多核CPU的并行处理时,通常采用多进程而不是多线程。然而,在多进程编程中,如何有效地在不同进程间共享变量成为了一个非常重要的课题。 在给定的例子中,作者通过一段代码展示了在没有正确使用共享变量的情况下,多个进程尝试修改同一个列表会导致最终的结果为空列表。具体代码如下: ```python from multiprocessing import Process, Manager import os manager = Manager() vip_list = [] # vip_list应为manager.list()以支持跨进程共享 def testFunc(cc): vip_list.append(cc) print('processid:', os.getpid()) if __name__ == '__main__': threads = [] for ll in range(10): t = Process(target=testFunc, args=(ll,)) t.daemon = True threads.append(t) for i in range(len(threads)): threads[i].start() for j in range(len(threads)): threads[j].join() print("------------------------") print('processid:', os.getpid()) print(vip_list) ``` 在这段代码中,每个子进程都会调用`testFunc`函数,并试图向`vip_list`添加元素。但是,由于`vip_list`是在主进程中定义的一个普通列表,所以它不会被各个子进程所共享。因此,每个子进程实际上都是在修改自己的私有列表副本,导致最终打印出的`vip_list`为空。 #### 二、Python多进程共享变量的方法 为了实现多进程之间的数据共享,可以采用以下两种方法: ##### (1)Shared memory:共享内存 通过`multiprocessing`库提供的`Value`或`Array`类,可以在进程间共享基本类型的数据,如整型、浮点型等。例如: ```python from multiprocessing import Process, Value, Array def f(n, a): n.value = 3.1415927 for i in range(len(a)): a[i] = -a[i] if __name__ == '__main__': num = Value('d', 0.0) arr = Array('i', range(10)) p = Process(target=f, args=(num, arr)) p.start() p.join() print(num.value) print(arr[:]) ``` 运行结果: ``` 3.1415927 [0, -1, -2, -3, -4, -5, -6, -7, -8, -9] ``` 这里使用`Value`创建了一个双精度浮点类型的共享变量`num`,以及使用`Array`创建了一个整型数组`arr`。在子进程中对这些变量的修改会立即反映到其他进程。 ##### (2)Server process:管理进程 通过`Manager()`返回的对象来控制一个服务器进程,该进程持有Python对象并允许其他进程通过代理操作这些对象。`Manager()`支持的类型包括:`list`, `dict`, `Namespace`, `Lock`, `RLock`, `Semaphore`, `BoundedSemaphore`, `Condition`, `Event`, `Queue`, `Value` 和 `Array` 等。例如: ```python from multiprocessing import Process, Manager import os def testFunc(vip_list, cc): vip_list.append(cc) print('processid:', os.getpid()) if __name__ == '__main__': manager = Manager() vip_list = manager.list() # 使用Manager创建的list支持跨进程共享 processes = [] for ll in range(10): p = Process(target=testFunc, args=(vip_list, ll)) p.daemon = True processes.append(p) for p in processes: p.start() for p in processes: p.join() print("-------------") print('processid:', os.getpid()) print(vip_list) ``` 运行结果: ``` processid: 32074 processid: 32073 processid: 32072 ... ------------- processid: 32066 [3, 2, 1, 7, 5, 0, 6, 8, 4, 9] ``` 这里我们使用`Manager()`创建了一个可以被多个进程共享的列表`vip_list`,这样就可以实现多进程间的变量共享。 #### 三、多进程的数据同步问题 除了变量共享之外,多进程编程还涉及到数据同步问题。当多个进程尝试同时修改共享数据时,如果没有适当的同步机制,就可能会导致数据损坏。下面是一个简单的计数器示例: ```python from multiprocessing import Process, Value def increment(count): count.value += 1 if __name__ == '__main__': count = Value('i', 0) processes = [Process(target=increment, args=(count,)) for _ in range(10)] for p in processes: p.start() for p in processes: p.join() print(count.value) ``` 这段代码中,多个进程尝试对共享的整数值`count`进行加一操作。理论上,如果没有任何同步措施,结果应该是10。但由于存在竞争条件(race condition),实际运行结果可能不是预期的10。 为了避免这种竞争条件,可以使用锁(Lock)来保护共享资源,确保同一时间只有一个进程能够访问共享资源。例如,修改上述计数器示例中的`increment`函数: ```python from multiprocessing import Process, Value, Lock def increment(lock, count): with lock: count.value += 1 if __name__ == '__main__': count = Value('i', 0) lock = Lock() processes = [Process(target=increment, args=(lock, count)) for _ in range(10)] for p in processes: p.start() for p in processes: p.join() print(count.value) ``` 在这个例子中,我们引入了`Lock`对象来确保每次只有一个进程能够修改`count`变量,从而避免了竞争条件的发生。 总结来说,Python多进程编程中涉及的变量共享问题可以通过共享内存和管理进程两种方式解决。此外,对于需要同步访问的数据,可以使用锁等同步原语来保证数据的一致性和完整性。这些技巧对于编写高效的多进程程序至关重要。
- 粉丝: 3
- 资源: 906
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 基于STM32的智能家居系统全部资料+详细文档+优秀项目.zip
- 基于阿里云的智能家居控制APP全部资料+详细文档+优秀项目.zip
- 基于stm32智能家居项目全部资料+详细文档+优秀项目.zip
- 基于安卓与STM32通信硬件开发项目,实现安卓端控制家庭灯,窗帘,门,有毒有害其他报警等,全部资料+详细文档+优秀项目.zip
- 基于安卓的智能家居项目源码,通过Zigbee网络控制采集家居设备实现管理功能、全部资料+详细文档+优秀项目.zip
- 基于从零开始打造一个智能家居系统全部资料+详细文档+优秀项目.zip
- 基于单片机课程实践——智能家居系统(安卓端)全部资料+详细文档+优秀项目.zip
- 基于机智云平台打造的物联网智能家居一体化智能App、全部资料+详细文档+优秀项目.zip
- 基于电力线载波智能家居控制系统全部资料+详细文档+优秀项目.zip
- 基于使用Qt制作的智能家居上位机全部资料+详细文档+优秀项目.zip
- 基于使用“树莓派+Django+bootstrap”搭建的智能家居监控系统全部资料+详细文档+优秀项目.zip
- 基于米家智能门锁接入开源智能家居系统全部资料+详细文档+优秀项目.zip
- 基于使用STM32、ESP8266、微信小程序搭建的MQTT智能家居全部资料+详细文档+优秀项目.zip
- 基于树莓派Linux智能家居自定义语音助手, 全部资料+详细文档+优秀项目.zip
- 基于天猫精灵智能家居技能对接homeassistant全部资料+详细文档+优秀项目.zip
- 基于一组Python脚本程序,用来控制小米智能家居设备全部资料+详细文档+优秀项目.zip