我运行了这段代码
NUM = 0
def count():
global NUM
NUM += 1
time.sleep(1)
print(t.getName()+":"+"NUM is "+str(NUM))
for i in range(10):
t = threading.Thread(target=count)
t.start()
输出
Thread-10:NUM is 10
Thread-10:NUM is 10
Thread-10:NUM is 10
Thread-10:NUM is 10
Thread-10:NUM is 10
Thread-10:NUM is 10
Thread-10:NUM is 10
Thread-10:NUM is 10
Thread-10:NUM is 10
Thread-10:NUM is 10
我知道为什么NUM总是10,但为什么线程名称总是一样的?每个线程都运行print(t.getName()+":"+"NUM is "+str(NUM))
; t
不应该是获得cpu时间的线程吗?我认为名称不应该相同。
当我改为
时NUM = 0
def count():
global NUM
NUM += 1
name = t.getName()
time.sleep(1)
print(name+":"+"NUM is "+str(NUM))
for i in range(10):
t = threading.Thread(target=count)
t.start()
它按预期工作:
Thread-1:NUM is 10
Thread-3:NUM is 10
Thread-2:NUM is 10
Thread-4:NUM is 10
Thread-5:NUM is 10
Thread-7:NUM is 10
Thread-10:NUM is 10
Thread-9:NUM is 10
Thread-6:NUM is 10
Thread-8:NUM is 10
答案 0 :(得分:7)
这是因为您引用了全局名称t
。当休眠结束时,循环结束,t
仍然绑定到循环创建的最后一个线程(第10个线程)。
在您的替代方案中,结果实际上并未定义。在那里你引用全局t
,而循环仍然在运行,所以它很可能被绑定到最近创建的线程 - 但是没有到是
注意:如果您无法方便地访问当前正在运行的线程对象,则可以使用
threading.currentThread()
得到它。然后
threading.currentThread().getName()
将返回运行它的线程的名称。
答案 1 :(得分:4)
您的函数查询t
,但函数中定义了否t
:
def count():
global NUM
NUM += 1
name = t.getName() # use outer t
time.sleep(1)
print(name+":"+"NUM is "+str(NUM))
Python的回退机制因此将在直接外部范围内寻找t
。实际上,您在外部范围内分配了t
,因此它将采用该值。
现在,因为您在t = ...
循环中编写 for
,t
会迅速变化。 for
循环很可能已经达到了最后一个值 - 特别是因为Python的线程机制 - 在第一个线程实际获取t
之前。因此,所有线程都会根据 last 构造的线程获取t
。
如果我们将该功能重写为:
NUM = 0
def count():
name = t.getName() # t fetched immediately
global NUM
NUM += 1
time.sleep(1)
print(name+":"+"NUM is "+str(NUM))
我明白了:
Thread-11:NUM is 10
Thread-12:NUM is 10
Thread-13:NUM is 10
Thread-14:NUM is 10
Thread-15:NUM is 10
Thread-17:NUM is 10
Thread-16:NUM is 10
Thread-19:NUM is 10
Thread-18:NUM is 10
Thread-10:NUM is 10
在我的机器上。当然,不保证每个线程都会获取正确的线程,因为有可能只是在进程的后期,线程才会开始工作并获取{{ 1}}变量。
答案 2 :(得分:2)
线程名称和计数NUM
都有同样的问题:当你到达第一个print
语句时,所有10个线程都已启动。您只有一个全局变量t
用于该线程,一个全局NUM
用于该计数。因此,您看到的只是最后一个值,即第10个线程的值。如果您希望打印单独的值,则需要为代码提供一种机制,以便在它们启动时对其进行报告,或者保留一个可以迭代的列表。
答案 3 :(得分:1)
我建议你试试这个:
NUM = 0
def count():
global NUM
NUM += 1
num = NUM
name = t.getName()
time.sleep(1)
print("t.getName: " + t.getName() + ", name: " + name + ":" + ", NUM: " + str(NUM) + ", num: " + str(num))
for i in range(10):
t = threading.Thread(target=count)
t.start()
结果:
t.getName: Thread-10, name: Thread-10:, NUM: 10, num: 10
t.getName: Thread-10, name: Thread-6:, NUM: 10, num: 6
t.getName: Thread-10, name: Thread-3:, NUM: 10, num: 3
t.getName: Thread-10, name: Thread-5:, NUM: 10, num: 5
t.getName: Thread-10, name: Thread-4:, NUM: 10, num: 4
t.getName: Thread-10, name: Thread-9:, NUM: 10, num: 9
t.getName: Thread-10, name: Thread-7:, NUM: 10, num: 7
t.getName: Thread-10, name: Thread-2:, NUM: 10, num: 2
t.getName: Thread-10, name: Thread-1:, NUM: 10, num: 1
t.getName: Thread-10, name: Thread-8:, NUM: 10, num: 8
t.getName()是一个函数调用,它是一个引用。当打印功能到达控制台时,t
引用最新的线程。