Reputation: 301
I ran this code
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()
The output is
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
I know why the NUM is always 10, but why is the thread name always the same? Every thread runs print(t.getName()+":"+"NUM is "+str(NUM))
; the t
should not be the thread that gets the cpu time's one? I think the name should not be the same.
When I changed to this
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()
It works as I expect:
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
Upvotes: 3
Views: 676
Reputation: 407
I advice you to try this:
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()
Result:
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() is a function call, which is a reference. By the time the print functions reached the console, t
references to the latest thread.
Upvotes: 1
Reputation: 476503
Your function queries for a t
, but no t
is defined in the function:
def count():
global NUM
NUM += 1
name = t.getName() # use outer t
time.sleep(1)
print(name+":"+"NUM is "+str(NUM))
The fallback mechanism of Python thus will look for a t
in the direct outer scope. And indeed, you assign to a t
in the outer scope, so it will take that value.
Now since you write t = ...
in a for
loop, that t
changes rapidly. It is very likely that the for
loop has already reached the last value - especially because of the threading mechanism of Python - before the first thread actually fetches that t
. As a result, all the threads fetch the t
referring to the last constructed thread.
If we however rewrite the function to:
NUM = 0
def count():
name = t.getName() # t fetched immediately
global NUM
NUM += 1
time.sleep(1)
print(name+":"+"NUM is "+str(NUM))
I get:
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
on my machine. Of course this does not guarantee that every thread will grab the correct thread, since it is possible that only later in the process, the thread will start working and fetches the t
variable.
Upvotes: 4
Reputation: 70572
It's because you're referencing the global name t
. By the time the sleeps end, the loop is over, and t
remains bound to the last thread (the 10th thread) the loop created.
In your alternative, the results aren't actually defined. There you reference the global t
while the loop is still running, so it's likely to be bound to the most recent thread created - but doesn't have to be.
Note: if you don't have convenient access to the thread object currently running, you can use
threading.currentThread()
to get it. Then
threading.currentThread().getName()
will return the name of the thread running it.
Upvotes: 7
Reputation: 77827
You have the same problem for both the thread name and the count NUM
: by the time you get to the first print
statement, all 10 threads have been started. You have only one global variable t
for the thread, and one global NUM
for the count. Thus, all you see is the last value, that for the 10th thread. If you want separate values printed, you need to supply your code with a mechanism to report them as they're launched, or keep a list through which you can iterate.
Upvotes: 2