我目前尝试使用线程编写更大的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
是必需的。尽管如此,脚本仍会运行。 我不明白这种行为。有人可以对此作出解释吗?
答案 0 :(得分:0)
global
用于允许分配全局变量。如果没有此声明,您可以读取未被遮蔽的全局变量。
对于上帝的爱,不要这样做。阅读有关管理并发的技术。
答案 1 :(得分:0)
需要global
语句来通知Python您希望变量(在这种情况下为var
)被视为全局的,可通用修改的名称,而不是每个函数的局部变量。如果您将var = 0
定义移到函数之上,那么您的价格会略微提高:
但是Marcin says,“因为上帝的爱不要这样做。”绕过几个NameError
并不是关键问题。即使没有并发性,很多程序也难以管理全局变量。在并发环境中,它们变成了噩梦。它们的行为在线程与多处理并发性方面也是非常不同的(你们两者都已导入,虽然你现在似乎在使用线程),并且跨越不同的平台(Windows的工作方式与Unix / Linux / Mac OS X不同,例如)。
您的数组引用至少在某种程度上起作用的原因是全局结构(例如字典,列表,NumPy数组)的内部内容很容易修改,即使整个结构不是这样。其中大部分与Python如何管理名称(粗略地说,“变量”)有关,而不是与并发性有关。但是在并发环境中,对这些全局结构的修改会很快变得过于冒险(阅读:令人困惑,不可靠,不易重现)。
所以,长话短说,在我们开始讨论你的线程所面临的race condition之前,这里有三到四个重叠的问题。
如果您的读者(child2
)的睡眠时间比您的作者(child1
)长,则基本上可以获得正常工作的代码。但请注意:除了玩具示例之外,您还需要一个真正的并发感知结构(例如a queue)。