import threading
n=0
def incn():
global n
for i in range(100000):
n+=1
task1=threading.Thread(target=incn)
task2=threading.Thread(target=incn)
task1.start()
task2.start()
task1.join()
task2.join()
print(n)
import threading
u=threading.Lock()
n=0
def incn():
global n
for i in range(100000):
u.acquire() #线程锁定资源
n+=1
u.release() #线程解锁资源
task1=threading.Thread(target=incn)
task2=threading.Thread(target=incn)
task1.start()
task2.start()
task1.join()
task2.join()
print(n)
上面两段代码都是使用两个线程分别对n进行100000次加1的操作,按照常理来说n被执行完之后应该为20000
然而第一段程序的结果不为200000且比200000小,第二段的结果为200000
原因归结于n+=1操作在运行时大致分为三步,首先将n的值读取到寄存器,对寄存器的值加1,再将寄存器的值赋值给n。
当两个线程同时进行时,可能会出现当第一个线程将n的值读到寄存器之后第二个线程也将n读到一个寄存器中,然后两个线程分别执行加1和赋值给n的操作,结果两次加1操作之后n只增加了1。所以会出现最后结果小于200000.
第二段程序使用了线程锁u=threading.Lock(),在线程中使用u.aquire()锁住对内存数据的操作,从而不会出现两个线程同时做对n加1的操作。
其中task1.start()为开始task1线程,task1.join()为等待task1线程执行结束后继续执行主线程后面的代码。