多处理不会使全局计数器工作

时间:2015-08-13 10:52:59

标签: python

我是新手,并尝试多次处理来控制全局计数器,但是下面的代码给出了global_counter'加入后为什么?为什么?!

from multiprocessing import Process, RLock

global_counter = 0

def counter(n, lock):
    global global_counter
    lock.acquire()
    global_counter += n
    lock.release()

def main(process_number):
    lock = RLock()
    pr_list = []
    for i in xrange(process_number):
        pr = Process(target=counter, args=(10, lock))
        pr_list.append(pr)
    for pr in pr_list:
        pr.start()
    for pr in pr_list:
        pr.join()


if __name__ == '__main__':
    main(10)
    print global_counter # it's still 0...

2 个答案:

答案 0 :(得分:0)

尝试使用multiprocessing.Value对象。您可以使用以下实现删除RLock对象:

from multiprocessing import Process, Value, Lock

def counter(n, shared_value, lock):
    with lock:
        shared_value.value += n

def main(process_number, shared_value):
    pr_list, lock = [], Lock()
    for i in xrange(process_number):
        pr = Process(target=counter, args=(10, shared_value, lock))
        pr_list.append(pr)

    for pr in pr_list:
        pr.start()
    for pr in pr_list:
        pr.join()

if __name__ == '__main__':
    shared_counter = Value("i", 0)
    main(10, shared_counter)
    print shared_counter.value # 100

这是因为2个进程不共享内存。子进程将拥有自己的内存副本,并且不会更新原始的global_counter变量。

但是,线程共享内存。

答案 1 :(得分:0)

threadingmultiprocessing之间存在深刻的差异。

基本上,线程是同一进程的一部分,共享所有数据,而multiprocessing使用的多个进程都有自己的数据(这是父进程的副本)新流程开始的那一刻)。因此每个子进程都有自己的独立global_counter。在这种情况下,使用FunkySayu建议的Value是一个很好的解决方案。

另一个值得关注的是,在CPython中,全局解释器锁强制执行,一次只有一个线程正在执行Python字节码。这意味着处理器密集型任务不会像预期的那样从线程中受益。将处理扩展到多个问题(使用multiprocessing)可以避免此问题。另一方面,在单独的过程中进行的计算的结果通常必须被传送回父过程。根据数据的大小,这也有开销。