Python多处理共享全局值

时间:2016-07-12 07:31:01

标签: python shared-memory python-multiprocessing

我想要做的是通过每个过程使用全局变量。 但我的过程并没有采取全球价值观

import multiprocessing

count = 0 

def smile_detection(thread_name):
    global count

    for x in range(10):
        count +=1
        print thread_name,count

    return count    

x = multiprocessing.Process(target=smile_detection, args=("Thread1",))
y = multiprocessing.Process(target=smile_detection, args=("Thread2",))
x.start()
y.start()

我得到像

这样的输出
Thread1 1
Thread1 2
.
.
Thread1 9
Thread1 10
Thread2 1
Thread2 2
.
.
Thread2 9
Thread2 10

我想要的是

Thread1 1
Thread1 2
.
.
Thread1 9
Thread1 10
Thread2 11
Thread2 12
.
.
Thread2 19
Thread2 20

我需要做些什么来实现这个目标?

4 个答案:

答案 0 :(得分:1)

与线程不同,由于新进程的分叉(或产生),多处理处理共享状态有点棘手。特别是在窗户。要拥有共享对象,请使用multiprocessing.Array或multiprocessing.Value。在数组的情况下,您可以在每个进程中取消引用其他结构中的内存地址,例如numpy数组。在你的情况下,我会做这样的事情:

import multiprocessing, ctypes

count = multiprocessing.Value(ctypes.c_int, 0)  # (type, init value)

def smile_detection(thread_name, count):

    for x in range(10):
        count.value +=1
        print thread_name,count

    return count    

x = multiprocessing.Process(target=smile_detection, args=("Thread1", count))
y = multiprocessing.Process(target=smile_detection, args=("Thread2", count))
x.start()
y.start()

答案 1 :(得分:1)

尝试这样做:

import multiprocessing

def smile_detection(thread_name, counter, lock):
    for x in range(10):
        with lock:
            counter.value +=1
            print thread_name, counter.value  


count = multiprocessing.Value('i',  0)
lock = multiprocessing.Lock()
x = multiprocessing.Process(target=smile_detection, args=("Thread1", count, lock))
y = multiprocessing.Process(target=smile_detection, args=("Thread2", count, lock))
x.start()
y.start()
x.join()
y.join()

第一个问题是全局变量不在进程之间共享。您需要使用具有某种线程安全锁定或同步类型的机制。我们可以使用multiprocessing.Value('i', 0)来创建线程安全的同步整数值。我们使用multiprocessing.Lock()来确保一次只有一个线程可以更新计数器。

如果您真的想使用全局变量,可以使用multiprocessing.Manager(),它可以保留在全局变量中:

import multiprocessing

count = multiprocessing.Manager().Value('i',  0)
lock = multiprocessing.Manager().Lock()

def smile_detection(thread_name):
    global count, lock

    for x in range(10):
        with lock:
            counter.value +=1
            print thread_name, counter.value  

x = multiprocessing.Process(target=smile_detection, args=("Thread1",))
y = multiprocessing.Process(target=smile_detection, args=("Thread2",))
x.start()
y.start()
x.join()
y.join()

但是,就个人而言,我更喜欢第一种方法,因为Manager()过于复杂。

现在输出:

$ python test.py
Thread1 1
Thread1 2
Thread1 3
Thread1 4
Thread1 5
Thread1 6
Thread1 7
Thread1 8
Thread1 9
...
Thread2 15
Thread2 16
Thread2 17
Thread2 18
Thread2 19
Thread2 20

答案 2 :(得分:1)

您可以使用multiprocessing.Value

  

返回从共享内存分配的ctypes对象。默认情况下,返回值实际上是对象的同步包装器。

代码如下:

import multiprocessing

count = multiprocessing.Value('i', 0)

def smile_detection(thread_name, count):
    for x in range(10):
        count += 1
        print thread_name, count

x = multiprocessing.Process(target=smile_detection, args=("Thread1",count))
y = multiprocessing.Process(target=smile_detection, args=("Thread2",count))

x.start()
y.start()
x.join()
y.join()

请注意,输出可能不是您期望的输出。事实上,在您的预期输出中,Thread 1的所有迭代都在Thread 2的迭代之前。在多线程应用程序中并非如此。如果您希望这种情况发生,那么您不希望它被线程化!

答案 3 :(得分:0)

要在mutiprocessing.Manager管理共享数据所需的流程之间共享数据:

count = multiprocessing.Manager().Value('i', 0) # creating shared variable
lock = multiprocessing.Manager().Lock() # we'll use lock to acquire lock on `count` before count += 1

def smile_detection(thread_name):
    global count

    for x in range(10):
        lock.acquire()
        count +=1
        lock.release()
        print thread_name,count

    return count