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]
  • 相关阅读:
    URAL 2080 莫队
    Codeforces Round #361 (Div. 2) C D
    UVALive 7297 bfs
    UVALive 7472
    HDU 5773 最长上升子序列
    递归求解最大值和最小值
    数字方阵旋转问题
    实现循环队列的各种基本运算
    实现顺序栈的各种基本运算
    使用两个栈来实现队列
  • 原文地址:https://www.cnblogs.com/blitheG/p/7522182.html
Copyright © 2011-2022 走看看