python多进程程序设计 之五
- 进程间通信
- Shared ctypes
- Value
- Array
- 实列代码
- sharedctypes
- RawArray
- RawValue
- Array
- Value
- 实列代码
进程间通信
Shared ctypes
Value
词法:multiprocessing.Value(typecode_or_type, *args, lock=True)
返回从共享内存分配的 ctypes 对象。默认情况下,返回值实际上是对象的同步包装器。可以通过 Value 的 value 属性来访问对象本身。
typecode_or_type 确定返回对象的类型:它是 ctypes 类型,或数组模块使用的一个字符的类型代码。 *args被作为这个类型的构造函数传递给这个构造器。
如果 lock 为 True(默认值),则创建一个新的递归锁对象,来同步对该值的访问。如果 lock 是 Lock 或 RLock 对象,那么,它将用于同步对该值的访问。如果lock为False,那么对返回对象的访问,将不会自动受到锁的保护,因此它不一定是“进程安全的”。
Array
词法:multiprocessing.Array(typecode_or_type, size_or_initializer, *, lock=True)
返回从共享内存分配的 ctypes 数组。默认情况下,返回值实际上是数组的同步包装器。
typecode_or_type 确定返回数组元素的类型:它是 ctypes 类型或数组模块使用的单字符类型代码。如果 size_or_initializer 是一个整数,那么它决定了数组的长度,并且数组最初将被清零。否则,size_or_initializer 是一个用于初始化数组的序列,其长度决定了数组的长度。
如果 lock 为 True(默认值),则创建一个新的锁对象,来同步对该值的访问。如果 lock 是 Lock 或 RLock 对象,那么,它将用于同步对该值的访问。如果lock为False,那么,对返回对象的访问将不会自动受到锁的保护,因此它不一定是“进程安全的”。
实列代码
from ctypes import *
import multiprocessing as mp
import timedef proc_0(a1, inc):print("start Process {0} inc: {1}".format(mp.current_process().name, inc))time.sleep(0.5)with a1.get_lock():for i in range(len(a1)):a1[i] += inc;print("Process {0} a1[{1}] = {2}".format(mp.current_process().name, i, a1[i]))time.sleep(0.2)def proc_1(a1, inc):print("start Process {0} inc: {1}".format(mp.current_process().name, inc))time.sleep(0.5)with a1.get_lock():for i in range(len(a1)):a1[i] += inc;print("Process {0} a1[{1}] = {2}".format(mp.current_process().name, i, a1[i]))time.sleep(0.1)if __name__ == "__main__": mp.freeze_support()a1 = mp.Array(c_int16, [1, 3, 4, 5]) p1 = mp.Process(target=proc_0, args=(a1, 4))p2 = mp.Process(target=proc_1, args=(a1, 7))p1.start()p2.start()p1.join()p2.join()
显示器输出
start Process Process-1 inc: 4
start Process Process-2 inc: 7
Process Process-1 a1[0] = 5
Process Process-1 a1[1] = 7
Process Process-1 a1[2] = 8
Process Process-1 a1[3] = 9
Process Process-2 a1[0] = 12
Process Process-2 a1[1] = 14
Process Process-2 a1[2] = 15
Process Process-2 a1[3] = 16
sharedctypes
multiprocessing.sharedctypes 模块提供了从共享内存中分配 ctypes 对象的函数。
注意, 这些对象可以由子进程继承。
RawArray
词法:multiprocessing.sharedctypes.RawArray(typecode_or_type, size_or_initializer)
返回从共享内存分配的 ctypes 数组。
- typecode_or_type,确定返回数组元素的类型。它是 ctypes 类型,或数组模块使用的单字符类型代码。
- size_or_initializer, 如果 size_or_initializer 是一个整数,那么,它确定数组的长度,并且,数组最初将被清零。否则,size_or_initializer 是一个用于初始化数组的序列,其长度决定了数组的长度。
读/写RawArray元素,可能是非原子的。所以,如果数据的读/写需要同步,则需要使用同步机制。
RawValue
词法:multiprocessing.sharedctypes.RawValue(typecode_or_type, *args)
返回从共享内存分配的 ctypes 对象。
- typecode_or_type,确定返回对象的类型。它是 ctypes 类型或数组模块使用的单字符的类型代码。
- args,被传递给该类型的构造函数。
读/写值可能是非原子的。所以,如果数据的读/写需要同步,则需要使用同步机制,或使用 Value() ,来确保使用锁自动同步访问。
Array
词法:multiprocessing.sharedctypes.Array(typecode_or_type, size_or_initializer, *, lock=True)
与 RawArray() 相同。只是根据 lock 的值,返回进程安全的同步包装器,而不是原始 ctypes 数组。
Value
词法:multiprocessing.sharedctypes.Value(typecode_or_type, *args, lock=True)
与 RawValue() 相同,只是根据 lock 的值,返回进程安全的同步包装器,而不是原始 ctypes 对象。
实列代码
这个代码在两个进程之间共享一个结构数组,因为使用了RawArray,RawArray不包含用于进程同步的锁,所以增加一个锁变量,用来同步两个进程对数组的存取。
from ctypes import *
import multiprocessing as mp
import time
import multiprocessing.sharedctypes as sc;class employee(Structure):_pack_ = 1_fields_ = [("year", c_int16), ("month", c_int16), ("day", c_int16)]def proc_0(inc, lock, a1):print("start Process {0} inc: {1}".format(mp.current_process().name, inc))time.sleep(0.5)with lock:for i in range(len(a1)):a1[i].year += inc;print("Process {0} a1[{1}] = {2}".format(mp.current_process().name, i, a1[i].year))time.sleep(0.2)def proc_1(inc, lock, a1):print("start Process {0} inc: {1}".format(mp.current_process().name, inc))time.sleep(0.5)with lock:for i in range(len(a1)):a1[i].year += inc;print("Process {0} a1[{1}] = {2}".format(mp.current_process().name, i, a1[i].year))time.sleep(0.1)if __name__ == "__main__":mp.freeze_support()a1 = sc.RawArray(employee, 3)a1[0].year = 2010a1[1].year = 2015a1[2].year = 2017lock = mp.Lock()dargs = {"a1":a1, "lock":lock}p1 = mp.Process(target=proc_0, args=(4,), kwargs=dargs)p2 = mp.Process(target=proc_1, args=(7,), kwargs=dargs)p1.start()p2.start()p1.join()p2.join()
start Process Process-1 inc: 4
start Process Process-2 inc: 7
Process Process-1 a1[0] = 2014
Process Process-1 a1[1] = 2019
Process Process-1 a1[2] = 2021
Process Process-2 a1[0] = 2021
Process Process-2 a1[1] = 2026
Process Process-2 a1[2] = 2028