多线程模块threading之互斥锁
下面这个例子,每次num输出的结果会不同,函数中的range()参数是10000,当参数小于10000的时候,num输出会是一个固定的值,比如100,那么num = 0,a1,a2两个函数各执行100次num += 1,最后输出的num为200,那么之所以range参数大了之后,计算结果会每次都不同,原因是因为多线程的资源竞争,a1的一次计算还没结束,a2又开始执行了,而因为a1没执行完毕+1的动作,那么a2获取的num值则没有更新,参数越大,这种概率越大。
因为num += 1,在运行时,实际上是三句代码:
1、获取num的值
2、给num的值+1
3、将2的值重新赋给num
锁住num+=1,就保证了执行这三句的时会执行完毕,而不会只执行到第二句,还没来的及给全局的num赋值,另外一个进程又获取未来得及被前一个线程赋值的全局num。
import threading
num = 0
def a1():
for i in range(1000000):
global num
num += 1
def a2():
global num
for i in range(1000000):
num += 1
print(num)
w = threading.Thread(target=a1)
u = threading.Thread(target=a2)
w.start()
u.start()
time.sleep(2)#停留2秒,等待子进程执行完毕
print(num)
解决办法:互斥锁
#创建锁
mutex = threading.Lock()
#锁定
mutex.acquire()
#释放
mutex.release()
还是上面的例子,加上互斥锁:
import time import threading num = 0 def a1(): global num #上锁,如果之前没有锁,此时锁 #如果之前已经锁了,此时会堵塞在这里 mutex.acquire() for i in range(1000000): num += 1 #解锁 mutex.release() def a2(): global num #上锁 mutex.acquire() for i in range(1000000): num += 1 #解锁 mutex.release() #创建互斥锁,默认没有上锁 mutex = threading.Lock() w = threading.Thread(target=a1) u = threading.Thread(target=a2) w.start() u.start() time.sleep(2) print(num)
现在每次运行程序,输出的num结果都是2000000。但是测试发现,这样会先完全执行完一个for循环后,再执行另外一个for循环
所以,如果调整一下上锁的位置,可以让两个for循环同时跑:
但是注意,sleep的参数改成了10,好像这样效率反而更慢了,奇怪!猜想可能是因为这样上锁解锁的次数太多导致的,原来每个for循环只需要上锁解锁一次就可以,现在range的参数是多少,就需要多少次解锁上锁,所以需要的时间反而长了,但是如果加锁中的代码比num+=1复杂的时候,这样并行的效率就可以体现出来了吧。
import time
import threading
num = 0
def a1():
global numfor i in range(1000000):
mutex.acquire()
num += 1
#解锁
mutex.release()
def a2():
global num
for i in range(1000000):
mutex.acquire()
num += 1
#解锁
mutex.release()
#创建互斥锁,默认没有上锁
mutex = threading.Lock()
w = threading.Thread(target=a1)
u = threading.Thread(target=a2)
w.start()
u.start()
time.sleep(10)
print(num)

浙公网安备 33010602011771号