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

Threading in Python and global variables - difference between arrays and standard variables?

我目前尝试使用线程编写更大的 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

需要。尽管如此,该脚本仍将 运行。 我不明白这种行为。有人可以解释一下吗?

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

  2. 看在上帝的份上,请不要这样做。阅读有关管理并发性的技术。

需要 global 语句来通知 Python 您希望变量(在本例中为 var)被视为全局的、普遍可修改的名称而不是局部的每个函数的变量。如果将 var = 0 定义移到函数上方,您的情况会稍微好一些:

但是作为 ,"For the love of god don't do this." 绕过一些 NameErrors 并不是这里的关键问题。全局变量在很多程序中都很难管理,即使没有并发也是如此。在并发环境中,它们变成了噩梦。它们的行为在线程与多处理并发(两者都已导入,尽管您目前似乎正在使用线程)以及跨不同平台(Windows 与 Unix/Linux/Mac 工作方式不同)方面也非常不同OS X,例如)。

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

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

如果您的 reader (child2) 的睡眠时间比您的编写器 (child1) 的睡眠时间长,您可能能够获得基本可用的代码。但要注意:除了玩具示例之外的任何东西,您都需要一个真正的并发感知结构(例如 a queue)。