zoukankan      html  css  js  c++  java
  • python

    在代码优化的过程中,碰到了这样一个问题:一个进程中我定义了几个全局变量,然后我又Process了几个子进程,子进程中是否可以各自对全局变量进行修改?最后全局变量会取哪个值呢?

    经过一番尝试以后得到结果:

      子进程继承父进程的全局变量,而且是以复制的形式完成,所以子进程修改后的全局变量只对自己和自己的子进程有影响。

      父子进程不共享这些全局变量,也就是说:父进程中对全局变量的修改不影响子进程中的全局变量,同理,子进程也不影响父进程的。

    为了实现父子进程的通信,在网上经过了一番翻找以后,找到了 Value和Array 方法

      Value函数返回一个shared memory包装类,其中包含一个ctypes对象

        一般 整数用 i, 字符用 c,浮点数用 d 就可以了

      Array函数返回一个shared memory包装类,其中包含一个数组,字符串需要用 Array 来传递

    • @args shared memory 中包含的值
    • @lock 默认值是True:创建一个新的lock来控制对value的访问。该参数也可以是 multiprocessing.Lock 或 multiprocessing.RLock 对像,用来控制对value的访问

    ================================================================================================================================  

    案例一:

    def worker(num, mystr, arr):
        num.value *= 2
        mystr.value = "ok"
        for i in range(len(arr)):
            arr[i] = arr[i] * (-1) + 1.5
     
    def dump_vars(num, mystr, arr):
        print 'num: ', num.value
        print 'str: ', mystr[:]
        print 'arr: ', arr[:]
     
    if __name__=='__main__':
        num = Value('i', 5)
        mystr = Array('c', 'just for test')
        arr = Array('d', [1.0, 1.5, -2.0])
        dir(str)
        print 'init value'
        dump_vars(num, mystr, arr)
     
        ps = [Process(target=worker, args=(num, mystr, arr)) for x in range(3)]
        for p in ps:
            p.start()
        for p in ps:
            p.join()
     
        print
        print 'after all workers finished'
        dump_vars(num, mystr, arr)
    #结果:
    init value
    num:  5
    str:  just for test
    arr:  [1.0, 1.5, -2.0]
    
    after all workers finished
    num:  40
    str:  ok

    多次测试我发现,在共享字符串的时候,在主进程中的初始化决定了这个字符串的长度,
    创建后字符串的长度固定不变,相当于把这个字符串所在的地址复制给一个指针,并且在字符串的首地址记录了自身的长度,
    在以后读取这个值的时候就会去读取那一段固定长度的内容,而不管现在的新内容长度是多少,举个例子:
    比如我们在主进程初始化一段字符串 "abcde",一旦初始化,长度就固定了,现在长度是5,然后我们在其他进程赋值,我们尝试赋值为
    "abcdefg",此时执行会报错,因为长度超标了,我们在赋值为 "yes",最后输出结果为 "yes&efg"(此处的&是代表一个不可显示的字符,不同的环境下显示不同,有可能显示空格,有可能显示null)。也就是说长短都不行,必须和初始化字符串等长。
    于是得出这样一个结论,如果你要共享一个字符串,那么在子进程中赋值时必须赋值长度相当的字符串。建议在子进程中可以先检查字符串长度,然后在根据需要拼接指定长度的字符串

    案例二:

    from multiprocessing import Process, Value, Array
    
    def f(n, a):
        n.value = n.value + 1
        for i in range(len(a)):
            a[i] = a[i] * 10
    
    if __name__ == '__main__':
        num = Value('i', 1)
        arr = Array('i', range(10))
    
        p = Process(target=f, args=(num, arr))
        p.start()
        p.join()
    
        print(num.value)
        print(arr[:])
       
        p2 = Process(target=f, args=(num, arr))
        p2.start()
        p2.join()
    
        print(num.value)
        print(arr[:])
    
    # the output is :
    # 2
    # [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
    # 3
    # [0, 100, 200, 300, 400, 500, 600, 700, 800, 900]
  • 相关阅读:
    C#listbox使用方法
    poj 3894 System Engineer (二分图最大匹配--匈牙利算法)
    Java实现 蓝桥杯VIP 算法训练 连接字符串
    Java实现 蓝桥杯VIP 算法训练 连接字符串
    Java实现 蓝桥杯VIP 算法训练 比较字符串
    Java实现 蓝桥杯VIP 算法训练 比较字符串
    Java实现 蓝桥杯VIP 算法训练 比较字符串
    Java实现 蓝桥杯VIP 算法训练 比较字符串
    Java实现 蓝桥杯VIP 算法训练 比较字符串
    Java实现 蓝桥杯VIP 算法训练 黑白无常
  • 原文地址:https://www.cnblogs.com/blitheG/p/7522182.html
Copyright © 2011-2022 走看看