I'm trying to get the result below running 2 threads alternately. *Between 0 to 5, thread A prints even numbers and thread B prints odd numbers (I use Python 3.8.5):
A:0
B:1
A:2
B:3
A:4
B:5
So, with global variables, locks and while statements, I created the code below to try to get the result above:
import threading
lock = threading.Lock()
owner = "A"
i = 0
def test1():
global owner, i
while i <= 5:
lock.acquire()
if owner == "A":
print(owner + ":" + str(i))
owner = "B"
i += 1
lock.release()
def test2():
global owner, i
while i <= 5:
lock.acquire()
if owner == "B":
print(owner + ":" + str(i))
owner = "A"
i += 1
lock.release()
A = threading.Thread(target=test1)
B = threading.Thread(target=test2)
A.start()
B.start()
A.join()
B.join()
But, the code above got the result below with A:6. *Thread A printed even number 6:
A:0
B:1
A:2
B:3
A:4
B:5
A:6 # Here
I couldn't find any mistakes so how can I get the proper result without A:6? And, why did I get the result with A:6?
The reason you are seeing the issue, is that the thread is still within the while loop when
imoves from5to6. The thread seems to obtain lock before the value is updated. i.e. The speed of release and lock is quicker than the assignment ofi. So the thread goes through one more round, but the only check you have is if the owner is equal toAorB. So you have to once again have the check in place to test thati<=5.If you had a single thread, then you would not have this issue, but because you are using two threads, you have to think of them as different entities, doing their own jobs. While
iis being updated in one thread, the other thread is still spinning and checking, locking and unlocking.The best way to visualise the thread actions is to have
printstatements within the lock (before the if-statement) - to see what each thread is up to.OUTPUT: