Reputation: 5730
This is a code for testing Threading
:
import threading
import time
episode = 0
lock = threading.Lock()
class Agent(threading.Thread):
def __init__(self, id):
threading.Thread.__init__(self)
self.id = id
def run(self):
global episode
while episode < 5:
with lock:
print(
"{} : episode will be changed {} -> {}".format(
self.id,
episode,
episode+1
)
)
episode += 1
print("{} : changed value -> {}".format(self.id, episode))
time.sleep(1)
if __name__ == "__main__":
agents = []
for i in range(3):
agents.append(Agent(i))
for agent in agents:
agent.start()
Result:
0 : episode will be changed 0 -> 1
0 : changed value -> 1
0 : episode will be changed 1 -> 2
0 : changed value -> 2
0 : episode will be changed 2 -> 3
0 : changed value -> 3
0 : episode will be changed 3 -> 4
0 : changed value -> 4
0 : episode will be changed 4 -> 5
0 : changed value -> 5
1 : episode will be changed 5 -> 6
1 : changed value -> 6
2 : episode will be changed 6 -> 7
2 : changed value -> 7
This is one of result that I had expected:
0 : episode will be changed 0 -> 1
0 : changed value -> 1
2 : episode will be changed 1 -> 2
2 : changed value -> 2
1 : episode will be changed 2 -> 3
1 : changed value -> 3
2 : episode will be changed 3 -> 4
2 : changed value -> 4
0 : episode will be changed 4 -> 5
0 : changed value -> 5
.
.
I can not understand why thread id=0 keep appearing consecutively in the first place... As I know of, the execution order of threads is random, right?
What's wrong in my code?
Upvotes: 2
Views: 1866
Reputation: 20206
You are just unlucky? I have tested your code without changing anything and got the following output:
0 : episode will be changed 0 -> 1
0 : changed value -> 1
1 : episode will be changed 1 -> 2
1 : changed value -> 2
2 : episode will be changed 2 -> 3
2 : changed value -> 3
2 : episode will be changed 3 -> 4
2 : changed value -> 4
2 : episode will be changed 4 -> 5
2 : changed value -> 5
0 : episode will be changed 5 -> 6
0 : changed value -> 6
1 : episode will be changed 6 -> 7
1 : changed value -> 7
Upvotes: 1
Reputation: 70582
Thread 0 starts first, grabs the lock, and sleeps while holding the lock. There is a very short period of time between the sleep ending, the lock getting released as a result of exiting the with
block, and the loop acquiring the lock again, so chances are excellent that thread 0 will get the lock again ... and again, and again, until episode < 5
is finally false.
Remove a level of indentation on your time.sleep(1)
so it executes as part of the loop instead of as part of the with
block. Then thread 0 will release the lock before starting its sleep, and other threads are almost certain to get the lock while thread 0 is sleeping (they have a whole second to do so then, instead of far less than an eyeblink).
Upvotes: 2