2015-07-21 143 views
-1

我目前尝试使用线程编写一个更大的python程序,并遇到了数组不必被声明为全局的问题。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未被声明为全局变量,因此上述代码将产生错误消息。 Unnotement

global var 

产生一个可执行脚本,打印var的值两次。 但是用numpy的阵列data_np,没有声明需要

global data_np 

时。脚本将运行。 我不明白这种行为。有人可以对此作出解释吗?

回答

0

global陈述要求通知的Python你想要一个变量(var在这种情况下)被视为一个全球性的,普遍的修改名称,而不是为每个函数的局部变量。如果您将var = 0的定义移到以上功能上,您的票价会稍微好一些:

但是由于Marcin says“对于上帝的爱不要这样做”。避开几个NameError这里并不是关键问题。全局变量在很多程序中很难管理,即使没有并发性。在并发环境中,他们变成了噩梦。它们在线程和多处理并发性(您已经导入了两者,尽管目前似乎使用线程)以及跨不同平台(Windows的工作方式与Unix/Linux/Mac OS X不同,例如, )。

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

因此,长话短说,在我们甚至开始讨论您的主题所面临的race condition之前,这里很容易出现三到四个重叠问题。

如果您的阅读器(child2)的睡眠时间比您的作者(child1)长,您可能可以获得基本工作代码。但要小心:除了一个玩具的例子,你需要一个真正的并发感知结构(例如a queue)。

+0

谢谢你的回答!它为底层结构提供了一个很好的第一见解。 – kM00n

+0

也许为了使事情更清楚,代码只是一个例子,以澄清我遇到的数组和标准变量被区别对待的问题。在我的主程序中,我想要创建两个进程,一个进行绘图,另一个进程包含两个线程。一个用于与外部设备通信的线程,另一个用于处理用户输入。我尝试通过仅分别向一个进程或线程写入变量或数组来避免并发性。到目前为止,这在OSX下得到了解决。 – kM00n

+0

是的。如果你只从一个线程写入结构,这大大简化了事情。由于“竞赛条件”,这并不意味着你会得到100%可靠的结果。对于这些,你需要真正的并发感知结构,比如队列。对于简单的示范,你有时可以不使用它们。 –

0
  1. global用于允许分配给全局变量。没有这个声明,你可以读取一个没有被遮蔽的全局变量。

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