多线程模块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)

 

posted @ 2019-01-04 15:51  greenfan  阅读(263)  评论(0)    收藏  举报