day9-为什么需要线程锁(互斥锁)

一、概述

线程需要沟通,需要共享数据,但是我们之前并没有涉及到多线程情况共享数据的例子。下面我们就来探讨一下,多线程共享数据会出现什么情况。这边就需要用到线程锁,又叫互斥锁(mutex)。

二、线程锁(互斥锁)

2.1、前戏

说明:我们现在来探讨多线程数据共享的情况

 1 import threading,time
 2 
 3 def run(n):
 4    #ock.acquire()
 5     global num
 6     time.sleep(1)
 7     num+=1
 8     #lock.release()
 9 
10 num=0
11 t_obj=[]
12 #lock=threading.Lock()
13 for i in range(100):
14     t = threading.Thread(target=run,args=("t-{0}".format(i),))
15     t.start()
16     t_obj.append(t)
17 
18 for t  in t_obj:
19     t.join()
20 
21 
22 print("-----all thead has finished")
23 print("num",num)

这个时候有些小伙伴就说了,你最后输出的结果怎么会是 97 呢?应该是100才对啊,不是有GIL(全局解释器锁)已经控制了,这个到底是为什么呐?

答:注意了,这种情况只能在python2.x 中才会出现的,python3.x里面没有这种现象。下面我们就用一张图来解释一下这个原因。如图:

 

图解释:

  1. 到第5步的时候,可能这个时候python正好切换了一次GIL(据说python2.7中,每100条指令会切换一次GIL),执行的时间到了,被要求释放GIL,这个时候thead 1的count=0并没有得到执行,而是挂起状态,count=0这个上下文关系被存到寄存器中.
  2. 然后到第6步,这个时候thead 2开始执行,然后就变成了count = 1,返回给count,这个时候count=1.
  3. 然后再回到thead 1,这个时候由于上下文关系,thead 1拿到的寄存器中的count = 0,经过计算,得到count = 1,经过第13步的操作就覆盖了原来的count = 1的值,所以这个时候count依然是count = 1,所以这个数据并没有保护起来.

2.2、添加线程锁

说明:通过上面的图我们知道,结果依然是不准确的。所以我还要加一把锁,这个是用户级别的锁。

 1 import threading,time
 2 
 3 def run(n):
 4     lock.acquire()
 5     global num
 6     time.sleep(1)
 7     num+=1
 8     lock.release()
 9 
10 num=0
11 t_obj=[]
12 lock=threading.Lock()
13 for i in range(100):
14     t = threading.Thread(target=run,args=("t-{0}".format(i),))
15     t.start()
16     t_obj.append(t)
17 
18 for t  in t_obj:
19     t.join()
20 
21 
22 print("-----all thead has finished")
23 print("num",num)

小结:

  1. 用theading.Lock()创建一个lock的实例。
  2. 在线程启动之前通过lock.acquire()加加锁,在线程结束之后通过lock.release()释放锁。
  3. 这层锁是用户开的锁,就是我们用户程序的锁。跟我们这个GIL没有关系,但是它把这个数据相当于copy了两份,所以在这里加锁,以确保同一时间只有一个线程,真真正正的修改这个数据,所以这里的锁跟GIL没有关系,你理解就是自己的锁。
  4. 加锁,说明此时我来去修改这个数据,其他人都不能动。然后修改完了,要把这把锁释放。这样的话就把程序编程串行了。

三、使用场景

在用户层面加锁,使程序变成串行了,那我们在什么情况下用呢?

  1、我们在程序中间不能有sleep,因为程序变成串行,这样你再sleep,程序执行的时间就会变长。

  2、我们使用的时候确保数据量不是特别大,如果数据量大,也会影响我们的执行效率。

  3、如果你程序结束时,不释放锁的话,而且程序又是串行的,则就是占着坑,那永远在那边等着,所以最后需要释放锁。

posted @ 2018-03-19 11:13  东郭仔  阅读(250)  评论(0)    收藏  举报