Python中的线程和全局变量 - 数组和标准变量之间的差异?

时间:2015-07-21 22:14:13

标签: python multithreading numpy global

我目前尝试使用线程编写更大的python程序,并遇到了不必以某种方式将数组声明为全局的问题。

import numpy as np
import threading
import time
import ctypes
import multiprocessing
import random
import os


def child1():
    #global var
    starttime = time.time()
    for ite in range(10):
        #data_np[ite] = time.time()-starttime
        #print data_np[ite]
        var += 1
        print var
        time.sleep(1)

def child2():
    #global var
    for ite in range(10):
        #print data_np
        print var
        print "\n"
        time.sleep(1)


os.system("clear")
data_np = np.zeros(shape=(10), dtype="float")
var = 0

thread1 = threading.Thread(target=child1)
thread2 = threading.Thread(target=child2)

thread1.start()
thread2.start()

thread1.join()
thread2.join()

如上所述的代码将产生错误消息,因为var未被声明为全局变量。取消注释

global var

生成一个可执行脚本,将var的值打印两次。 但是当使用numpy数组data_np时,没有声明

global data_np

是必需的。尽管如此,脚本仍会运行。 我不明白这种行为。有人可以对此作出解释吗?

2 个答案:

答案 0 :(得分:0)

  1. global用于允许分配全局变量。如果没有此声明,您可以读取未被遮蔽的全局变量。

  2. 对于上帝的爱,不要这样做。阅读有关管理并发的技术。

答案 1 :(得分:0)

需要global语句来通知Python您希望变量(在这种情况下为var)被视为全局的,可通用修改的名称,而不是每个函数的局部变量。如果您将var = 0定义移到函数之上,那么您的价格会略微提高:

但是Marcin says,“因为上帝的爱不要这样做。”绕过几个NameError并不是关键问题。即使没有并发性,很多程序也难以管理全局变量。在并发环境中,它们变成了噩梦。它们的行为在线程与多处理并发性方面也是非常不同的(你们两者都已导入,虽然你现在似乎在使用线程),并且跨越不同的平台(Windows的工作方式与Unix / Linux / Mac OS X不同,例如)。

您的数组引用至少在某种程度上起作用的原因是全局结构(例如字典,列表,NumPy数组)的内部内容很容易修改,即使整个结构不是这样。其中大部分与Python如何管理名称(粗略地说,“变量”)有关,而不是与并发性有关。但是在并发环境中,对这些全局结构的修改会很快变得过于冒险(阅读:令人困惑,不可靠,不易重现)。

所以,长话短说,在我们开始讨论你的线程所面临的race condition之前,这里有三到四个重叠的问题。

如果您的读者(child2)的睡眠时间比您的作者(child1)长,则基本上可以获得正常工作的代码。但请注意:除了玩具示例之外,您还需要一个真正的并发感知结构(例如a queue)。